What does this ' ->' mean in c/objective-c? - objective-c

I'm looking over some code and I came across some syntax that I don't know the meaning of. What does the '->' mean?
-(void) getTransformValues:(struct transformValues_*) tv
{
tv->pos = positionInPixels_;
tv->scale.x = scaleX_;
tv->scale.y = scaleY_;
tv->rotation = rotation_;
tv->skew.x = skewX_;
tv->skew.y = skewY_;
tv->ap = anchorPointInPixels_;
tv->visible = visible_;
}

The arrow operator ('->') is used in the same place you would use the dot operator ('.'), but with a pointer to a structure instead of an object of that structure.
typedef struct _Person {
char name[200];
unsigned int age;
} Person;
If you created an object of that structure, you would use the dot operator in order to access its members:
int main()
{
Person p1;
strcpy( p1.name, "Baltasar" );
p1.age = 36;
}
However, if you a pointer to a structure, instead of the structure itself, you could only use the arrow operator, or a little bit more complex dot operator:
int main()
{
Person p1;
Person *ptrPerson = &p1; // ptrPerson points to p1
strcpy( ptrPerson->name, "Baltasar" );
ptrPerson->age = 36;
}
As I said above, you could still use the dot operator:
int main()
{
Person p1;
Person *ptrPerson = &p1; // ptrPerson points to p1
strcpy( (*ptrPerson).name, "Baltasar" );
(*ptrPerson).age = 36;
}
Of course, all of this discussion involves a lot more topics, such as pointers, the heap, etc. Hope this helps.

The -> symbol is used to access a member of a pointer type. It is the same as dereferencing the pointer and using the dot operator, i.e.,
(*tv).pos = positionInPixels_;

It's used to access a member of an object / struct pointed to by a variable.
For example tv->pos is used to access the member variable pos from the object pointed to by tv

-> is used to mean the same thing as the dot (which means to access a member of a structure, class, or union), except that -> is used when the variable is a pointer.

"->" is used in order to access a struct pointer element. In C at least...
typedef struct test {
int one;
int two;
} t_test;
t_test *foo;
/* Allocation and all the stuff */
foo->one = ...
foo->two = ...

The arrow operator (->) takes a struct pointer (to a transformValues_ in this case), dereferences it, then accesses that member variable.
IE: these are equivelant:
(* tv).pos === tv->pos

Hmmmm did you at least consider trying to find it out for yourself before posting here?
This is what I got from searching operators....

Related

How to use int[] type in Objective-C [duplicate]

I wrote a function containing array as argument,
and call it by passing value of array as follows.
void arraytest(int a[])
{
// changed the array a
a[0] = a[0] + a[1];
a[1] = a[0] - a[1];
a[0] = a[0] - a[1];
}
void main()
{
int arr[] = {1, 2};
printf("%d \t %d", arr[0], arr[1]);
arraytest(arr);
printf("\n After calling fun arr contains: %d\t %d", arr[0], arr[1]);
}
What I found is though I am calling arraytest() function by passing values, the original copy of int arr[] is changed.
Can you please explain why?
When passing an array as a parameter, this
void arraytest(int a[])
means exactly the same as
void arraytest(int *a)
so you are modifying the values in main.
For historical reasons, arrays are not first class citizens and cannot be passed by value.
For passing 2D (or higher multidimensional) arrays instead, see my other answers here:
How to pass a multidimensional [C-style] array to a function in C and C++, and here:
How to pass a multidimensional array to a function in C++ only, via std::vector<std::vector<int>>&
Passing 1D arrays as function parameters in C (and C++)
1. Standard array usage in C with natural type decay (adjustment) from array to ptr
#Bo Persson correctly states in his great answer here:
When passing an array as a parameter, this
void arraytest(int a[])
means exactly the same as
void arraytest(int *a)
Let me add some comments to add clarity to those two code snippets:
// param is array of ints; the arg passed automatically "adjusts" (frequently said
// informally as "decays") from `int []` (array of ints) to `int *`
// (ptr to int)
void arraytest(int a[])
// ptr to int
void arraytest(int *a)
However, let me add also that the above two forms also:
mean exactly the same as
// array of 0 ints; automatically adjusts (decays) from `int [0]`
// (array of zero ints) to `int *` (ptr to int)
void arraytest(int a[0])
which means exactly the same as
// array of 1 int; automatically adjusts (decays) from `int [1]`
// (array of 1 int) to `int *` (ptr to int)
void arraytest(int a[1])
which means exactly the same as
// array of 2 ints; automatically adjusts (decays) from `int [2]`
// (array of 2 ints) to `int *` (ptr to int)
void arraytest(int a[2])
which means exactly the same as
// array of 1000 ints; automatically adjusts (decays) from `int [1000]`
// (array of 1000 ints) to `int *` (ptr to int)
void arraytest(int a[1000])
etc.
In every single one of the array examples above, and as shown in the example calls in the code just below, the input parameter type adjusts (decays) to an int *, and can be called with no warnings and no errors, even with build options -Wall -Wextra -Werror turned on (see my repo here for details on these 3 build options), like this:
int array1[2];
int * array2 = array1;
// works fine because `array1` automatically decays from an array type
// to a pointer type: `int *`
arraytest(array1);
// works fine because `array2` is already an `int *`
arraytest(array2);
As a matter of fact, the "size" value ([0], [1], [2], [1000], etc.) inside the array parameter here is apparently just for aesthetic/self-documentation purposes, and can be any positive integer (size_t type I think) you want!
In practice, however, you should use it to specify the minimum size of the array you expect the function to receive, so that when writing code it's easy for you to track and verify. The MISRA-C-2012 standard (buy/download the 236-pg 2012-version PDF of the standard for £15.00 here) goes so far as to state (emphasis added):
Rule 17.5 The function argument corresponding to a parameter declared to have an array type shall have an appropriate number of elements.
...
If a parameter is declared as an array with a specified size, the corresponding argument in each function call should point into an object that has at least as many elements as the array.
...
The use of an array declarator for a function parameter specifies the function interface more clearly than using a pointer. The minimum number of elements expected by the function is explicitly stated, whereas this is not possible with a pointer.
In other words, they recommend using the explicit size format, even though the C standard technically doesn't enforce it--it at least helps clarify to you as a developer, and to others using the code, what size array the function is expecting you to pass in.
2. Forcing type safety on arrays in C
(Not recommended (correction: sometimes recommended, especially for fixed-size multi-dimensional arrays), but possible. See my brief argument against doing this at the end. Also, for my multi-dimensional-array [ex: 2D array] version of this, see my answer here.)
As #Winger Sendon points out in a comment below my answer, we can force C to treat an array type to be different based on the array size!
First, you must recognize that in my example just above, using the int array1[2]; like this: arraytest(array1); causes array1 to automatically decay into an int *. HOWEVER, if you take the address of array1 instead and call arraytest(&array1), you get completely different behavior! Now, it does NOT decay into an int *! This is because if you take the address of an array then you already have a pointer type, and pointer types do NOT adjust to other pointer types. Only array types adjust to pointer types. So instead, the type of &array1 is int (*)[2], which means "pointer to an array of size 2 of int", or "pointer to an array of size 2 of type int", or said also as "pointer to an array of 2 ints". So, you can FORCE C to check for type safety on an array by passing explicit pointers to arrays, like this:
// `a` is of type `int (*)[2]`, which means "pointer to array of 2 ints";
// since it is already a ptr, it can NOT automatically decay further
// to any other type of ptr
void arraytest(int (*a)[2])
{
// my function here
}
This syntax is hard to read, but similar to that of a function pointer. The online tool, cdecl, tells us that int (*a)[2] means: "declare a as pointer to array 2 of int" (pointer to array of 2 ints). Do NOT confuse this with the version withOUT parenthesis: int * a[2], which means: "declare a as array 2 of pointer to int" (AKA: array of 2 pointers to int, AKA: array of 2 int*s).
Now, this function REQUIRES you to call it with the address operator (&) like this, using as an input parameter a POINTER TO AN ARRAY OF THE CORRECT SIZE!:
int array1[2];
// ok, since the type of `array1` is `int (*)[2]` (ptr to array of
// 2 ints)
arraytest(&array1); // you must use the & operator here to prevent
// `array1` from otherwise automatically decaying
// into `int *`, which is the WRONG input type here!
This, however, will produce a warning:
int array1[2];
// WARNING! Wrong type since the type of `array1` decays to `int *`:
// main.c:32:15: warning: passing argument 1 of ‘arraytest’ from
// incompatible pointer type [-Wincompatible-pointer-types]
// main.c:22:6: note: expected ‘int (*)[2]’ but argument is of type ‘int *’
arraytest(array1); // (missing & operator)
You may test this code here.
To force the C compiler to turn this warning into an error, so that you MUST always call arraytest(&array1); using only an input array of the corrrect size and type (int array1[2]; in this case), add -Werror to your build options. If running the test code above on onlinegdb.com, do this by clicking the gear icon in the top-right and click on "Extra Compiler Flags" to type this option in. Now, this warning:
main.c:34:15: warning: passing argument 1 of ‘arraytest’ from incompatible pointer type [-Wincompatible-pointer-types]
main.c:24:6: note: expected ‘int (*)[2]’ but argument is of type ‘int *’
will turn into this build error:
main.c: In function ‘main’:
main.c:34:15: error: passing argument 1 of ‘arraytest’ from incompatible pointer type [-Werror=incompatible-pointer-types]
arraytest(array1); // warning!
^~~~~~
main.c:24:6: note: expected ‘int (*)[2]’ but argument is of type ‘int *’
void arraytest(int (*a)[2])
^~~~~~~~~
cc1: all warnings being treated as errors
Note that you can also create "type safe" pointers to arrays of a given size, like this:
int array[2]; // variable `array` is of type `int [2]`, or "array of 2 ints"
// `array_p` is a "type safe" ptr to array of size 2 of int; ie: its type
// is `int (*)[2]`, which can also be stated: "ptr to array of 2 ints"
int (*array_p)[2] = &array;
...but I do NOT necessarily recommend this (using these "type safe" arrays in C), as it reminds me a lot of the C++ antics used to force type safety everywhere, at the exceptionally high cost of language syntax complexity, verbosity, and difficulty architecting code, and which I dislike and have ranted about many times before (ex: see "My Thoughts on C++" here).
For additional tests and experimentation, see also the link just below.
References
See links above. Also:
My code experimentation online: https://onlinegdb.com/B1RsrBDFD
See also:
My answer on multi-dimensional arrays (ex: 2D arrays) which expounds upon the above, and uses the "type safety" approach for multi-dimensional arrays where it makes sense: How to pass a multidimensional array to a function in C and C++
If you want to pass a single-dimension array as an argument in a function, you would have to declare a formal parameter in one of following three ways and all three declaration methods produce similar results because each tells the compiler that an integer pointer is going to be received.
int func(int arr[], ...){
.
.
.
}
int func(int arr[SIZE], ...){
.
.
.
}
int func(int* arr, ...){
.
.
.
}
So, you are modifying the original values.
Thanks !!!
Passing a multidimensional array as argument to a function.
Passing an one dim array as argument is more or less trivial.
Let's take a look on more interesting case of passing a 2 dim array.
In C you can't use a pointer to pointer construct (int **) instead of 2 dim array.
Let's make an example:
void assignZeros(int(*arr)[5], const int rows) {
for (int i = 0; i < rows; i++) {
for (int j = 0; j < 5; j++) {
*(*(arr + i) + j) = 0;
// or equivalent assignment
arr[i][j] = 0;
}
}
Here I have specified a function that takes as first argument a pointer to an array of 5 integers.
I can pass as argument any 2 dim array that has 5 columns:
int arr1[1][5]
int arr1[2][5]
...
int arr1[20][5]
...
You may come to an idea to define a more general function that can accept any 2 dim array and change the function signature as follows:
void assignZeros(int ** arr, const int rows, const int cols) {
for (int i = 0; i < rows; i++) {
for (int j = 0; j < cols; j++) {
*(*(arr + i) + j) = 0;
}
}
}
This code would compile but you will get a runtime error when trying to assign the values in the same way as in the first function.
So in C a multidimensional arrays are not the same as pointers to pointers ... to pointers. An int(*arr)[5] is a pointer to array of 5 elements,
an int(*arr)[6] is a pointer to array of 6 elements, and they are a pointers to different types!
Well, how to define functions arguments for higher dimensions? Simple, we just follow the pattern!
Here is the same function adjusted to take an array of 3 dimensions:
void assignZeros2(int(*arr)[4][5], const int dim1, const int dim2, const int dim3) {
for (int i = 0; i < dim1; i++) {
for (int j = 0; j < dim2; j++) {
for (int k = 0; k < dim3; k++) {
*(*(*(arr + i) + j) + k) = 0;
// or equivalent assignment
arr[i][j][k] = 0;
}
}
}
}
How you would expect, it can take as argument any 3 dim arrays that have in the second dimensions 4 elements and in the third dimension 5 elements. Anything like this would be OK:
arr[1][4][5]
arr[2][4][5]
...
arr[10][4][5]
...
But we have to specify all dimensions sizes up to the first one.
You are not passing the array as copy. It is only a pointer pointing to the address where the first element of the array is in memory.
You are passing the address of the first element of the array
You are passing the value of the memory location of the first member of the array.
Therefore when you start modifying the array inside the function, you are modifying the original array.
Remember that a[1] is *(a+1).
Arrays in C are converted, in most of the cases, to a pointer to the first element of the array itself. And more in detail arrays passed into functions are always converted into pointers.
Here a quote from K&R2nd:
When an array name is passed to a function, what is passed is the
location of the initial element. Within the called function, this
argument is a local variable, and so an array name parameter is a
pointer, that is, a variable containing an address.
Writing:
void arraytest(int a[])
has the same meaning as writing:
void arraytest(int *a)
So despite you are not writing it explicitly it is as you are passing a pointer and so you are modifying the values in the main.
For more I really suggest reading this.
Moreover, you can find other answers on SO here
In C, except for a few special cases, an array reference always "decays" to a pointer to the first element of the array. Therefore, it isn't possible to pass an array "by value". An array in a function call will be passed to the function as a pointer, which is analogous to passing the array by reference.
EDIT: There are three such special cases where an array does not decay to a pointer to it's first element:
sizeof a is not the same as sizeof (&a[0]).
&a is not the same as &(&a[0]) (and not quite the same as &a[0]).
char b[] = "foo" is not the same as char b[] = &("foo").
Arrays are always passed by reference if you use a[] or *a:
int* printSquares(int a[], int size, int e[]) {
for(int i = 0; i < size; i++) {
e[i] = i * i;
}
return e;
}
int* printSquares(int *a, int size, int e[]) {
for(int i = 0; i < size; i++) {
e[i] = i * i;
}
return e;
}
An array can also be called as a decay pointer.
Usually when we put a variable name in the printf statement the value gets printed in case of an array it decays to the address of the first element, Therefore calling it as a decay pointer.
And we can only pass the decay pointer to a function.
Array as a formal parameter like Mr.Bo said int arr[] or int arr[10] is equivalent to the int *arr;
They will have there own 4 bytes of memory space and storing the decay pointer received.and we do pointer arithmetic on them.

Different Objective-C enums with the same literals

I wish to have two different enums, but they might have the same literal; for example:
typedef enum {ONE,TWO,THREE,FOUR,FIVE,SIX} NumbersEnum;
typedef enum {ONE,TWO,THREE,FIVE,EIGHT} FibonacciEnum;
This will raise a compile error because ONE, TWO, THREE, FIVE are repeated in both enums.
Is there a way to make this work as-is (not changing the literals' names or adding a prefix or suffix)?
Is there any way my code using the literals can look like this: int num = NumbersEnum.SIX; and not like this int num = SIX;?
No. That's part of the C and Objective-C language from the beginning of time. You're not going to change it, and nobody is going to change it for you.
You cannot do this with enums; their members are global and the names must be unique. There is, however, a neat technique you can use to make pseudo-namespaces for constants with structs.
Declare your "namespace" in the appropriate header:
extern const struct _FibonacciNumbers
{
int one;
int two;
int three;
int five;
} FibonacciNumbers;
Then initialize the values in an implementation file:
const struct _FibonacciNumbers FibonacciNumbers = {
.one = 1,
.two = 2,
.three = 3,
.five = 5
};
You now access a constant as, e.g., FibonacciNumbers.one, and other struct types can use the same names since the names are private to each of them.
So that's "No" for your first option, but "Yes" to the second.

pointer to function syntax and usage

I apologize if this was asked many times.
I'm trying to understand why both of this works fine without any warnings or other visible issues (in Xcode):
int testFunctionAcceptingIntPointer(int * p) {
return *p = *p +5;
}
void test() {
int testY = 7;
typedef int (*MyPointerToFunction)(int*);
// Both this (simply a function name):
MyPointerToFunction functionPointer = testFunctionAcceptingIntPointer;
// And this works (pointer to function):
MyPointerToFunction functionPointer = &testFunctionAcceptingIntPointer;
int y = functionPointer(&testY);
}
The code works fine without warnings both ways because a function designator is converted to a function pointer
MyPointerToFunction functionPointer = testFunctionAcceptingIntPointer;
unless it is the operand of the address operator
MyPointerToFunction functionPointer = &testFunctionAcceptingIntPointer;
(or sizeof and _Alignof).
In the first assignment, you don't use &, so the automatic conversion is done, resulting in a function pointer of appropriate type, in the second, you explicitly take the address, resulting in a function pointer of the appropriate type.

Structure of a block declaration

When declaring a block what's the rationale behind using this syntax (i.e. surrounding brackets and caret on the left)?
(^myBlock)
For example:
int (^myBlock)(int) = ^(int num) {
return num * multiplier;
};
C BLOCKS: Syntax and Usage
Variables pointing to blocks take on the exact same syntax as variables pointing to functions, except * is substituted for ^. For example, this is a function pointer to a function taking an int and returning a float:
float (*myfuncptr)(int);
and this is a block pointer to a block taking an int and returning a float:
float (^myblockptr)(int);
As with function pointers, you'll likely want to typedef those types, as it can get relatively hairy otherwise. For example, a pointer to a block returning a block taking a block would be something like void (^(^myblockptr)(void (^)()))();, which is nigh impossible to read. A simple typedef later, and it's much simpler:
typedef void (^Block)();
Block (^myblockptr)(Block);
Declaring blocks themselves is where we get into the unknown, as it doesn't really look like C, although they resemble function declarations. Let's start with the basics:
myvar1 = ^ returntype (type arg1, type arg2, and so on) {
block contents;
like in a function;
return returnvalue;
};
This defines a block literal (from after = to and including }), explicitly mentions its return type, an argument list, the block body, a return statement, and assigns this literal to the variable myvar1.
A literal is a value that can be built at compile-time. An integer literal (The 3 in int a = 3;) and a string literal (The "foobar" in const char *b = "foobar";) are other examples of literals. The fact that a block declaration is a literal is important later when we get into memory management.
Finding a return statement in a block like this is vexing to some. Does it return from the enclosing function, you may ask? No, it returns a value that can be used by the caller of the block. See 'Calling blocks'. Note: If the block has multiple return statements, they must return the same type.
Finally, some parts of a block declaration are optional. These are:
The argument list. If the block takes no arguments, the argument list can be skipped entirely.
Examples:
myblock1 = ^ int (void) { return 3; }; // may be written as:
myblock2 = ^ int { return 3; }
The return type. If the block has no return statement, void is assumed. If the block has a return statement, the return type is inferred from it. This means you can almost always just skip the return type from the declaration, except in cases where it might be ambiguous.
Examples:
myblock3 = ^ void { printf("Hello.\n"); }; // may be written as:
myblock4 = ^ { printf("Hello.\n"); };
// Both succeed ONLY if myblock5 and myblock6 are of type int(^)(void)
myblock5 = ^ int { return 3; }; // can be written as:
myblock6 = ^ { return 3; };
source: http://thirdcog.eu/pwcblocks/
I think the rationale is that it looks like a function pointer:
void (*foo)(int);
Which should be familiar to any C programmer.

Confusion on passing in pointers to functions

I'm reading a book to learn Objective-C and this program is suppose to show key concepts in dealing with pointers, and I'm really lost.
Is there some kind of conversion happening in the function's arguments that turn p1, p2, &il, and &i2 to the value (*) of a pointer? Like p1 turns into *p1?
I thought a copy of the variable was passed into the function instead of the actual variable, so why was the value of the passed in variable changed after the function?
Also why am I getting a warning on the 3rd line that says: No previous prototype for function 'exchangeValues'?
Thank you!!
#import <Foundation/Foundation.h>
void exchangeValues (int *pint1, int *pint2) {
int temp;
temp = *pint1;
*pint1 = *pint2;
*pint2 = temp;
}
int main (int argc, char *argv[]) {
#autoreleasepool {
void exchangeValues (int *pint1, int *pint2);
int il = -5, i2 = 66, *p1 = &il, *p2 = &i2;
NSLog(#"il = %i, i2 = %i", il, i2);
exchangeValues(p1, p2);
NSLog(#"il = %i, i2 = %i", il, i2);
exchangeValues(&il, &i2);
NSLog(#"il = %i, i2 = %i", il, i2);
}
return 0;
}
Output:
2012-08-02 11:13:38.569 Test[381:707] il = -5, i2 = 66
2012-08-02 11:13:38.571 Test[381:707] il = 66, i2 = -5
2012-08-02 11:13:38.572 Test[381:707] il = -5, i2 = 66
I would say that's a complex example if you are being taught about pointers!
Is there some kind of conversion happening in the function's arguments
that turn p1, p2, &il, and &i2 to the value (*) of a pointer? Like p1
turns into *p1?
p1 and p2 are declared as int * (pointer to int) and are initialised with the address of i1 and i2 (using the & operator).
I thought a copy of the variable was passed into the function instead
of the actual variable, so why was the value of the passed in variable
changed after the function?
A copy of the variable is passed to the function, however in this case the variable of type int * (pointer to int). The reason the value is changing is because the exchangeValues() function is dereferencing those pointers and swapping the values. This is the only way (in C/Objective-C) a function can modify a variable outside of its own scope, other than the variable being assigned as the return value from a function.
Also why am I getting a warning on the 3rd line that says: No previous
prototype for function 'exchangeValues'?
You seem to have typed it in wrong; remove the line below #autoreleasepool:
#autoreleasepool {
void exchangeValues (int *pint1, int *pint2); <-- delete this line
If you pass a pointer into the function, it indeed passes a copy of that pointer- but it still refers to the same address in memory. So de-referencing that pointer will still point to a variable that's outside of the function scope.
I thought a copy of the variable was passed into the function instead of the actual variable, so why was the value of the passed in variable changed after the function?
A copy of the pointer is passed to the function here. So what the function has points to the memory locations the variables l1 and l2 are stored at. So
void exchangeValues (int *pint1, int *pint2) {
int temp;
temp = *pint1; // store the value that pint1 points to in temp
*pint1 = *pint2; // store the value pint2 points to where pint1 points to
*pint2 = temp; // store the value saved in temp where pint2 points to
}
its a little confusing how the variables have been declared and initialised all in a row like that but basically you have:
i1 is an int set to -5
p1 is a pointer to an int set to the address of i1
same goes for i2 and p2
No conversion is taking place. You're effectively 'swapping' the values that those pointers point to in the function.
Pointers are confusing things but stick with it and it will become clear with enough parctice and example code like this...