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

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.)

Related

What is the difference between (int *)array, (int *)&array, and &array in a pointer assignment?

I have 3 lines of code that performs exactly the same but have different syntax, the base code being:
int a, b;
printf("Enter the size of your array [a][b]: ");
scanf("%d %d", &a, &b);
int arr[a][b];
int *pa;
pa = (int *)&arr;
for (i = 0; i < a*b; i++)
{
printf("[%d] [%d] = ", i/b, i%b);
scanf("%d", (pa + i));
}
On the line pa = (int *)&arr;, I can switch that line to (int *)array, (int *)&array, and &array without encountering any issues, only experiencing a warning at the last one. I was wondering the correct syntax is and the difference between all 3 of them.
The correct syntax is pa = &arr[0]; and if you find yourself in need to add a cast, you are doing something wrong. Bluntly put, if you are a beginner, you shouldn't be casting pointers ever.
pa = &arr does not "only give a warning", it's invalid C. This is a so-called constraint violation - invalid assignment of non-compatible pointer types. Please study What compiler options are recommended for beginners learning C? and What must a C compiler do when it finds an error?
Similarly, pa = (int *)&array is an invalid pointer conversion between non-compatible types. It will compile but has a compiler-specific outcome. It's strictly speaking incorrect code but may work for the specific compiler and system.
pa = (int *)array is wrong for similar reasons too - since array has decayed into a pointer to array type which is not compatible with int*.
Two key tidbits:
The address of an array is the address of its first element.
When treated as a pointer, an array degrades into a pointer to its first element
So,
pa = arr;
is equivalent to
pa = &(arr[0]); // Type mismatch: RHS is int (*)[b]
You use a typecast to silence the error when doing pa = (int *)arr;.
pa = &arr;
is equivalent to
pa = &(arr[0]); // Type mismatch: RHS is int (*)[b]
You use a typecast to silence the error when doing pa = (int *)&arr;.
These typecasts are not safe. If you want to treat it as a 1d array of int values, best to declare it that way too.

Pointer with different type than the referenced variable

I am currently learning how to program in C. Today I started with pointers, and I encountered the following situation. When I compile the program
#include<stdio.h>
int main() {
int a;
double * p;
p = &a;
*p = 12.34;
printf("%d\n",a);
* (int *) p = 12.34;
printf("%d\n",a);
return 0;
}
it says
$ gcc zeigertypen.c
zeigertypen.c: In function ‘main’:
zeigertypen.c:7:7: warning: assignment from incompatible pointer type [-Wincompatible-pointer-types]
and upon execution, I get the output
2061584302
Speicherzugriffsfehler (Speicherabzug geschrieben)
The error message is German for something like
memory access error (core dumped)
However, if I comment out the line *p = 12.34; the error disappears and the output is
0
12
The purpose of the code is to demonstrate the problem with pointers of different type than the variable they are referencing. According to the textbook I'm using to learn C++, the output should be
2061584302
12
The behaviour of p = &a; is actually undefined.
Neither C nor C++ allow you to re-interpret the type of &a (which is a pointer to int) as a pointer to a double.
(int*)p is similarly problematic, although by then the damage has been done.
You are allowed to cast to void*, and back to the original type from void*: for now, regard these as being the only cases where you can cast the type of a pointer to a different type.
Explaination with code: (Acc to your Textbook)
#include<stdio.h>
int main() {
int a; // size let say (2 byte or 4 )
double * p; // it will point to continous memory of 8 byte
p = &a; // Now because of this ,starting from first byte of a it will derefer 8 bytes (but Undefined behaviour acc to C standards)
*p = 12.34; // assigned to those 8 bytes
printf("%d\n",a); // first (2 or 4 ) bytes of that value in *p assignment as it starts from a
* (int *) p = 12.34; // now you type casted it to derefer 2 bytes so store 12 in those (2 or 4) bytes as int
printf("%d\n",a); // first (2 or 4) bytes of that value in *p assignment
return 0;
}
if you need more explaination comment and ask me . Thank you.

Pointers in C syntax error

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);

What does (*ptr)[10] mean?

void main()
{
int (*d)[10];
d[0] = 7;
d[1]=10;
printf("%d\n",*d);
}
It should print 10 but compiler is showing error such as follows:
test.c:4:7: error: incompatible types when assigning to type ‘int[10]’ from type ‘int’
Note that I have included some errors , not all.
As noted by chris, d is a pointer to an array. This means you use the variable improperly when you access it, but also that you will access random memory unless you assign d to point to a valid array.
Change your program as follows:
int main(void)
{
int (*d)[10]; /* A pointer to an array */
int a[10]; /* The actual array */
d = &a; /* Make `d` point to `a` */
/* Use the pointer dereference operator (unary prefix `*`)
to access the actual array `d` points to */
(*d)[0] = 7;
(*d)[1] = 10;
/* Double dereference is okay to access the first element of the
arrat `d` points to */
printf("%d\n", **d);
return 0;
}
In C, [] is the same as *, the pointer syntax. Thus the following lines are the same:
int** array2d1;
int* array2d2[];
int array2d3[][];
To relate to a closer example, the main function has the following popular forms:
int main(int argc, char** argv){ ... }
or
int main(int argc, char* argv[]){ ... }
Thus
int (*d)[10]
is the same as
int* d[10]
which is the same as
int** d;
int firstArray[10];
d = &firstArray;
Effectively, you are creating a pointer to a pointer (which is a pointer to an array) and allocating the first pointer to an array that 10 elements. Therefore, when you run the following lines:
d[0] = 7;
d[1] = 10;
You are assigning the 1st array's address to 7 and the second array's address to 10. So as Joachim has mentioned, to assign values, you need to deference twice:
(*d)[0] = 7
(*d)[1] = 10
Which says "Assign 7 to the 0th index at the value pointed by d". I hope that makes sense?
d is a pointer to an array of 10 ints.
int (*d)[10] is the declaration for a point to an array of 10 ints.
vs.
int *d[10], which is an array of 10 int pointers.
For more complex syntax like this (usually involving pointers), I use cdecl to help me decode it.
It's used in this form
int d[10]
I guess you are mistaken that d must be a "kind of pointer" and therfor you put an * before the d.
But that's not what you want. You wan to name an array of integer and the notation for that is seen above.
Concept of pointer can get confusing sometimes in C.
Consider an array int d[6] = {0,1,2,3,4,5}
Then, *d is equivalent to d[0]. d is itself an pointer to an array and *d dereferences that pointer and gives us the value.
Hence, following code would print the same values:
int main()
{
int (d)[10];
*d = 7;
*(d + 1)=10;
printf("%d\n",*d);
printf("%d\n",d[0]);
return 0;
}
result:
7
7
Please see http://codepad.org/LYY9ig1i.
If you change your code as follows:
#include<malloc.h>
int main()
{
int *d[10]; //not (*d)[10]
d[0] = (int *)malloc(sizeof(int *) * 10);
d[0][0] = 7;
printf("%d\n",d[0][0]);
return 0;
}
Hope this helps you!

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