Pointers in C syntax error - c

Code given below illustrates use of pointers as an exercise:
#include<stdio.h>
struct s{
int *p;
};
int main(){
struct s v;
int *a = 5;
v->p = a;
printf("%d",v->p);
return 0;
}
Why is the syntax error:
invalid type argument -> (struct s)

As with many questions about C on StackOverflow, you need to go back to the basics.
x->y is a concise way to write (*x).y.
The * operator takes a pointer and gives you the variable associated with that pointer.
So now the answer to your question is straightforward. v->p = a; means the same thing as (*v).p = a; The * operator on the value of v turns the pointer v into a variable... but v isn't a pointer. It's a struct s. Therefore, this is an error; the * operator can only be applied to things of pointer type.

You've declared v to NOT be a pointer (struct s v; -- no *), and you're trying to use ->, which only works on pointers. You're also declaring a to be pointer (int *a -- has a *), but you're trying to initialize it with an integer.

To access a member of a struct object we use the dot . operator.
v.p = a;
When the struct object need to be acceded through a pointer then we use the operator ->.
struct s *vp = &v;
vp->p = a;
Also you're assigning an integer to an pointer
int *a = 5;
which is very dangerous since any try to dereference it leads to a crash.

The invalid type argument of ‘->’ (have ‘struct s’) error shows up in lines 8 & 9. Both try to reference the struct's elements using v->p. In this instance, you should change v->p to v.p. This is because 'v' has been allocated and is not a pointer.
This is a neat piece of code for playing with pointers. Once you get the v.p compiling, you are going to see some core dump every time you reference 'a'. This is because you are declaring 'a' as a pointer and not allocating any space for the actual integer value. Try adding the following code to see where it goes:
int b = 5;
int* a = &b;
printf("%d\n", b);
printf("%d\n", *a);
printf("%d\n", a);

Related

Passing struct with 2d array to thread function and getting value of it's index

I am trying to pass struct to thread. Unfortunatelty when it happens i can no longer use p[i][j]. I am getting error: subscripted value is neither array nor pointer nor vector
typedef struct MY_M {
int *p1;
int *p2;
} MY_M;
int *M1[r];
for (i=0; i<r; i++){
M1[i] = (int *)malloc(c * sizeof(int));}
pthread_t thread1;
struct MY_M *p = malloc(sizeof(struct MY_M));
p-> p1 = *M1;
p-> p1 = *M2;
int ret = pthread_create(&thread1,NULL,thread,(void*) p);
thread here:
void* thread(void* parameter )
{
MY_M **p = (MY_M*)parameter;
p->p1[0][0] = 5;
}
When i comment p[0][0] the program is working fine. Why it is not working? I would be grateful for any help.
I can't tell exactly what you are trying to accomplish here, but I can see a number of errors.
In the first place, you assign two values to p->p1. I assume this is probably a mistake and you meant to assign one value to p->p1 and another to p->p2. (And where did M2 come from?)
Second, int *M1[r]; will allocate r pointers to int on the stack, which means the array containing the buffers will become invalidated shortly after the function returns.
You are also dereferencing M1 during assignment, which means you are only pointing to the first buffer that you allocated. Again, I can't tell exactly what you are trying to do with that, so I don't know what to recommend.
p1 is also type int*, which means it contains the address of an int, so it can only be dereferenced once and will resolve to int. If you want to dereference it twice (p->p1[x][y]) it should be type int** or pointer to some other dereference-able type.
Also, you cast parameter to MY_M*, but then assign it to a variable of type MY_M**. That is not correct (in fact, isn't that giving you a compiler error?)
As far as I can tell, you are simply trying to allocate some structure that your thread will later have access to. If that is the case, the code would be something like this:
typedef struct MY_M {
int* p1;
int* p2;
} MY_M;
MY_M* p = (MY_M*)malloc( sizeof(MY_M) );
p->p1 = (int*)malloc( c * sizeof(int) );
p->p2 = (int*)malloc( c * sizeof(int) );
pthread_t thread1;
int ret = pthread_create(&thread1, NULL, thread, (void*)p);
thread here:
void* thread(void* parameter)
{
MY_M *p = (MY_M*)parameter;
p->p1[0] = 5;
}
Overall, it seems that you don't fully understand pointers properly. I can try to give a brief rundown, but do consult other guides and references to fully understand the concept.
First: a pointer is an address. So int* a = &b; means that a of type int* will contain b's address, and therefore it points to b. If you dereference a pointer, that means you take the address value that it holds and follow the address to its original source. So *a dereferences a, resolving to the value stored in b.
Array index syntax is equivalent to offset + dereferencing, so when you say p->p1[0][0], that is really equivalent to *((*(p->p1+0))+0), which dereferences the variable twice.
You can't dereference something that isn't a pointer (i.e., doesn't contain an address). That's why your int* can't be dereferenced twice. After dereferencing it once, it is now an int, which does not contain an address and cannot be dereferenced.
I hope this helps.
What you're actually using is an array of pointers (to arrays), rather than a proper 2D array -- though that isn't really a problem here. As for why it isn't working, you simply have the wrong type for p in your thread function -- it should be int ** rather than int *.

how, where and why someone would use int (*q)[3];

I was reading this question on stackoverflow
C pointer to array/array of pointers disambiguation
I came across int (*q)[3]; // q is a pointer to array of size of 3 integers
The discussion was quite on understanding complex declarations in C.
Iam unable to understand when it is used and how it is used? how do I dereference it? could anyone explain me with some sample codes, like initializing the pointer and dereferencing it.
int main(){
int a =45;
int c[3] = {23};
int b[2][3];
int d[2][5];
int (*q)[3];
b[0][0]=1;
b[0][1]=2;
b[0][0]=3;
q = &a; // warning incompatible pointer type
q = c; // warning incompatible pointer type
q = b; // no warnings works fine
q = d; // warning incompatible pointer type
return 0;
}
After trying the above statements, I understood q can point to an array of n row but 3 column sized array. How do I dereference those values?
printf("%d",*q); gives some strange value 229352.
Could anyone explain me how to initialize and how to dereference the pointers and its memory layout?
Since q can point to an array, you have to
make its value the address of an array: q = &c;, and
dereference it to get an array: ++(*q)[1], printf("%d", (*q)[2]), etc.
Note that the rows of b are also arrays of type int[3], so you can also assign to q the address of each row of b:
q = b + 0; // (*q)[i] == b[0][i]
q = b + 1; // (*q)[i] == b[1][i]
(By contrast, the rows of d have type int[5], so their addresses are not compatible with the type of q, and of course the address of a is also not compatible, since the type if a is int.)

Pointer to array not functioning as expected

I am expanding my knowledge of arcane C usage, especially with strange pointer types. I found a site with some examples and I've been trying them out. However, after playing with some of these examples, I found some strange behaviour relating to a pointer to an array. Here is the code:
int test = 45;
int *testp = &test;
int (*p)[1];
p = &testp;
printf("%d\n", **p);
This code outputs 2686744 (which I can make no sense of). My logic is as follows: an array is just a glorified pointer. I can make a pointer and call it an array of 1 if I like. So when I create the pointer testp, I expect it to function as an array of 1 int. Furthermore, I would expect the line int (*p)[1]; to create an int** variable. However, there is something even worse about the whole thing. Here is a modified version of the above code:
int test[1] = {45};
int (*p)[1];
p = &test;
printf("%d\n", **p);
This outputs 45, as expected. So, my question is, what is the difference between these two snippets that causes the first to output garbage?
Thanks
This code snippet is invalid and shall not be compiled
int test = 45;
int *testp = &test;
int (*p)[1];
p = &testp;
printf("%d\n", **p);
The type of expression &testp is int ** while in the left side of the assignment there is an object of type int (*)[1]. There is no implicit conversion from one type to enother.
Nevertheless dereferencing p in the function call
printf("%d\n", **p);
that is *p will give array of type int[1] However the value stored in *p is the value of testp. Thus the only element of the array is the value stored in testp that is the address of test (provided that sizeof( int * ) is equal to sizeof( int ).
So the output of the function is the address of test.
The second code snippet is valid. *p is an array with one element and **P gives the value of the first element of the aray.

Given the address of a pointer, how do I get what it points to?

If I am given the address of a pointer, how do I get what the pointer points to?
You might mean:
/**
* #param pointer_to_pointer_to_int: the address of a pointer to an integer.
**/
void function_that_takes_pointer_to_pointer(int **pointer_to_pointer_to_int) {
int the_int = **pointer_to_pointer_to_int;
printf("The pointer points to %d\n", the_int);
}
Assuming it is a valid pointer, you can dereference it using the unary * operator:
int *ptr = ...;
int x;
x = *ptr;
The unary * operator.
int *ptr = malloc(sizeof(int));
*ptr = 45;
printf("address: %p, value: %d", ptr, *ptr);
The most common way to be given the address of a pointer is through a pointer to a pointer. If the value the pointer points to is an integer, the type of the address of the pointer is int **.
To get the pointer to the integer, you need to dereference the double pointer. Then you can dereference the integer pointer to get the integer value.
To dereference a pointer, use the * operator.
int **double_pointer = given;
int *int_pointer = *double_pointer;
int value = *int_pointer;
You can also chain the dereferences to do that on one line.
int **double_pointer = given;
int value = **double_pointer;
The unary * operator returns or sets the value at a memory location.
For example:
int val = 42;
int* ptr = &val;
assert(val == *ptr);
If you have the address of a pointer, you would write **pointerpointer.
Going off of RedX's comment, If you have a situation like
void foo(void *ptr)
{
...
}
where the value of ptr is a pointer to a pointer to int, for example, you could do something like
void foo(void *ptr)
{
int x = **((int **) ptr);
...
}
Basically, you cast ptr to int **, then double-dereference it.
If you don't know what the target type is ahead of time (e.g., the function is meant to handle pointers to multiple types), then you're going to have to figure out a way to encode that type information in a second argument and pass it to the function.
There are two possible answers to your question depending on whether the compiler has a clue about the data that's referred or not.
Declaring a pointer of type int *, char * or mytype * instructs the compiler that a later attempt to dereference it using the unary * operator must yield a result of int, char or mytype respectively.
In the other case you would normally store a pointer either in a void * (generic, untyped pointer) or in a uintptr_t (an unsigned int the same size of a pointer, but without pointer semantics). In such a case the compiler doesn't have a clue how to interpret the dereferencing operator, so you must explicitly cast such a pointer to another pointer type, and only then dereference it:
int x = 5;
void *p = &x; /* p now points to an int, but the compiler doesn't know it */
printf("%d\n", *((int *) p)); /* we know what we did and don't rely on the compiler */
printf("%d\n", *p); /* compile-time error, dereferencing has undefined semantics */
Note that in compiled, unmanaged languages like C there is no runtime information about what kind of data a pointer is pointing to, unlike languages like Java where you can use the instanceof operator to check what a reference is really pointing to at runtime.

Understanding C: Pointers and Structs

I'm trying to better understand c, and I'm having a hard time understanding where I use the * and & characters. And just struct's in general. Here's a bit of code:
void word_not(lc3_word_t *R, lc3_word_t A) {
int *ptr;
*ptr = &R;
&ptr[0] = 1;
printf("this is R at spot 0: %d", ptr[0]);
}
lc3_word_t is a struct defined like this:
struct lc3_word_t__ {
BIT b15;
BIT b14;
BIT b13;
BIT b12;
BIT b11;
BIT b10;
BIT b9;
BIT b8;
BIT b7;
BIT b6;
BIT b5;
BIT b4;
BIT b3;
BIT b2;
BIT b1;
BIT b0;
};
This code doesn't do anything, it compiles but once I run it I get a "Segmentation fault" error. I'm just trying to understand how to read and write to a struct and using pointers. Thanks :)
New Code:
void word_not(lc3_word_t *R, lc3_word_t A) {
int* ptr;
ptr = &R;
ptr->b0 = 1;
printf("this is: %d", ptr->b0);
}
Here's a quick rundown of pointers (as I use them, at least):
int i;
int* p; //I declare pointers with the asterisk next to the type, not the name;
//it's not conventional, but int* seems like the full data type to me.
i = 17; //i now holds the value 17 (obviously)
p = &i; //p now holds the address of i (&x gives you the address of x)
*p = 3; //the thing pointed to by p (in our case, i) now holds the value 3
//the *x operator is sort of the reverse of the &x operator
printf("%i\n", i); //this will print 3, cause we changed the value of i (via *p)
And paired with structs:
typedef struct
{
unsigned char a;
unsigned char r;
unsigned char g;
unsigned char b;
} Color;
Color c;
Color* p;
p = &c; //just like the last code
p->g = 255; //set the 'g' member of the struct to 255
//this works because the compiler knows that Color* p points to a Color
//note that we don't use p[x] to get at the members - that's for arrays
And finally, with arrays:
int a[] = {1, 2, 7, 4};
int* p;
p = a; //note the lack of the & (address of) operator
//we don't need it, as arrays behave like pointers internally
//alternatively, "p = &a[0];" would have given the same result
p[2] = 3; //set that seven back to what it should be
//note the lack of the * (dereference) operator
//we don't need it, as the [] operator dereferences for us
//alternatively, we could have used "*(p+2) = 3;"
Hope this clears some things up - and don't hesitate to ask for more details if there's anything I've left out. Cheers!
I think you are looking for a general tutorial on C (of which there are many). Just check google. The following site has good info that will explain your questions better.
http://www.cplusplus.com/doc/tutorial/pointers/
http://www.cplusplus.com/doc/tutorial/structures/
They will help you with basic syntax and understanding what the operators are and how they work. Note that the site is C++ but the basics are the same in C.
First of all, your second line should be giving you some sort of warning about converting a pointer into an int. The third line I'm surprised compiles at all. Compile at your highest warning level, and heed the warnings.
The * does different things depending on whether it is in a declaration or an expression. In a declaration (like int *ptr or lc3_word_t *R) it just means "this is a pointer."
In an expression (like *ptr = &R) it means to dereference the pointer, which is basically to use the pointed-to value like a regular variable.
The & means "take the address of this." If something is not a pointer, you use it to turn it into a pointer. If something is already a pointer (like R or ptr in your function), you don't need to take the address of it again.
int *ptr;
*ptr = &R;
Here ptr is not initialized. It can point to whatever. Then you dereference it with * and assign it the address of R. That should not compile since &R is of type lc3_word_t** (pointer to pointer), while *ptr is of type int.
&ptr[0] = 1; is not legal either. Here you take the address of ptr[0] and try to assign it 1. This is also illegal since it is an rvalue, but you can think of it that you cannot change the location of the variable ptr[0] since what you're essentially trying to do is changing the address of ptr[0].
Let's step through the code.
First you declare a pointer to int: int *ptr. By the way I like to write it like this int* ptr (with * next to int instead of ptr) to remind myself that pointer is part of the type, i.e. the type of ptr is pointer to int.
Next you assign the value pointed to by ptr to the address of R. * dereferences the pointer (gets the value pointed to) and & gives the address. This is your problem. You've mixed up the types. Assigning the address of R (lc3_word_t**) to *ptr (int) won't work.
Next is &ptr[0] = 1;. This doesn't make a whole lot of sense either. &ptr[0] is the address of the first element of ptr (as an array). I'm guessing you want just the value at the first address, that is ptr[0] or *ptr.

Resources