Double Pointer to Array in C - c

Below is a code snippet and the outputs:
int main()
{
int A[2][3] = {{1100, 1200, 1300}, {1400, 1500, 1600}};
int (*p)[3], (**q)[3];
p = A;
q = A;
printf("*p is : %d\n", *p);
//Output : *p is : -547221600
printf("*q is : %d", *q);//Why ?
//Output : *q is : 1100
}
p is a pointer to integer array of size 3. *p + i points to ith array in A i.e. A[i].
What would happen if instead I use double pointers (q in the above code).
I am unable to understand that why *q gives 1100 as the value.

For starters this assignment
q = A;
is incorrect because the left operand (having the type int ( ** )[3]) and the right operand (having the type int ( * )[3] after the implicit conversion of the array designator to a pointer to its first element) have different types and there is no implicit conversion between the types.
The compiler can issue an error like this
error: assignment to ‘int (**)[3]’ from incompatible pointer type ‘int (*)[3]’
You could write instead
q = &p;
In this call of printf
printf("*p is : %d\n", *p);
there is used an incorrect argument. The type of the expression *p is int[3]. So in fact you are trying to output a pointer (due to implicit conversion of the array designator to a pointer to its first element) using the conversion specifier %d that is designed to output integers.
Here is a demonstrative program.
#include <stdio.h>
int main(void)
{
int A[2][3] = {{1100, 1200, 1300}, {1400, 1500, 1600}};
int (*p)[3], (**q)[3];
p = A;
q = &p;
printf( "A is : %p\n", ( void * )A );
printf( "*p is : %p\n", ( void * )*p );
printf( "*q is : %p\n", ( void * )*q);
return 0;
}
Its output might look like
A is : 0x7ffdb1c214e0
*p is : 0x7ffdb1c214e0
*q is : 0x7ffdb1c214e0
That is the first call of printf output the initial address of the first element A[0] (of the type int[3]) of the two-dimensional array.
The second call of printf outputs the address of the first element of the first "row" of the two-dimensional array that is &A[0][0].
The third call of printf outputs the value stored in the pointer p that is the address of the first "row" of the two-dimensional array A.
If you want to output the first elements of the array A using the pointers then the program can look the following way.
#include <stdio.h>
int main(void)
{
int A[2][3] = {{1100, 1200, 1300}, {1400, 1500, 1600}};
int (*p)[3], (**q)[3];
p = A;
q = &p;
printf( "**p is : %d\n", **p );
printf( "***q is : %d\n", ***q);
return 0;
}
Now the program output is
**p is : 1100
***q is : 1100

p is a pointer to integer array of size 3.
Correct.
*p + i points to ith array in A i.e. A[i].
Incorrect. p + i would be a pointer to an array.
When you indirect through the pointer to array, the result is an array, and when you add an integer to an array, the array decays to pointer to element of that array and since *p is an array of integers, the decayed pointer points to an integer element of the array. Thus, the result of *p + i is a pointer to an integer (i'th sibling of the first element of the first array).
What would happen if instead I use double pointers (q in the above code).
I assume that by substituted above code, you mean *q + i.
If you have a pointer to a pointer to an array, then indirecting through the pointer results in a pointer to an array. Adding an integer to pointer to an array gives you pointer to an array that is a sibling.
q = A;
This assignment is ill-formed in C++. An array of arrays of integers is not convertible to a pointer to pointer to an array.
printf("*p is : %d\n", *p);
printf("*q is : %d", *q);//Why ?
%d is an invalid format specifier for int* as well as for a int (*)[3]. By using invalid format specifier, the behaviour of this program is undefined. That explains all of the behaviour.

Related

the size of distance between two pointers

void main() {
int a = 2;
int *p = &a;
int *q = p++;
printf("%d %d\n", p, q);
int b = p - q;
printf("%d", b);
}
Why does it print 1? I've tried with other pointers but didn't succeed. I thought it would print the size of int because the distance between them is 1 * sizeof(int) but it prints 1.
why it prints 1?
Because C specifies pointer subtraction as the difference in the indexes (subscript) of the array, not the difference in address values.
1 past the object is like the an array element after the int a;
For the purposes of these operators, a pointer to an object that is not an element of an array behaves the same as a pointer to the first element of an array of length one with the type of the object as its element type. C17dr § 6.5.6 7
When two pointers are subtracted, both shall point to elements of the same array object, or one past the last element of the array object; the result is the difference of the subscripts of the two array elements. The size of the result is implementation-defined, and its type (a signed integer type) is ptrdiff_t defined in the <stddef.h> header. § 6.5.6 8
Subscript 1 - subcript 0 --> 1.
The result is 1 even if int a was char a or long double a.
For starters according to the C Standard the function main without parameters shall be declared like
int main( void )
To output pointers you have to write
printf("%p %p\n", ( void * )p, ( void * )q);
In the initializer of the pointer q
int* q = p++;
there is used an expression with the postfix increment operator. Its value is the value of the operand before incrementing.
So the pointer q is initialized by the address of the variable a and as a side effect the pointer p is incremented and points to the memory after the object a. That is between the addresses (in the extent of memory bounded by these addresses) stored in the pointers p and q there is stored only one object a. So according to the pointer arithmetic the result of the expression p - q is 1.
On the other hand, the difference between the addresses stored in the pointers p and q is equal to the value of sizeof( int ) that is to the value of sizeof( a ).
If you will write for example
int b = ( char * )p - ( char * )q;
then the value of b will be equal to sizeof( a ) because in this case the memory occupied by the variable a is interpreted as a character array and sizeof( char ) is always equal to 1.
There are a few errors in this code:
The return type of main() should be int instead of void.
The printf() statement has two integer format specifiers, but the arguments passed are pointers, which are not guaranteed to have the same size as integers. Therefore, using the %d format specifier to print pointers is not correct. You can use the %p format specifier to print pointers.
The variables p and q are pointers to int, so the difference between them (i.e., p - q) should be divided by the size of int to get the number of elements between them.
Here is the corrected code:
#include <stdio.h>
int main() {
int a = 2;
int* p = &a;
int* q = p++;
printf("%p %p\n", p, q);
int b = (p - q) / sizeof(int);
printf("%d", b);
return 0;
}
This code will print the memory addresses of p and q, followed by the difference between them in terms of the number of int elements.

Pointer to a 2D array

I have a 2D array (int s[4][2])and I created a pointer as int (*p)[2].
The pointer p is now assigned the address of 1st element of row within a for loop.
for (int i = 0; i<4; i++)
p = &s[i];
Now when I try to write the array elements data using dereferencing, I get wrong values.
printf ("%d \n", *p)
However, if I create another pointer and link that with the previous pointer
int *ptr = p;
and dereference pointer ptr I get correct values.
printf ("%d \n", *ptr)
When both the pointers are pointing to the same address why does one pointer (*ptr) work as expected and other (*p) does not return expected values?
If p is a pointer to array then *p is array of 2 ints (int[2]). So, you can't print an array element like this:
printf ("%d \n", *p);
To print the array elements through the pointer p, you need to do:
printf ("%d \n", (*p)[0]); /* first element */
printf ("%d \n", (*p)[1]); /* second element */
p is not a pointer to an int. It is a pointer to an array of two int. Therefore *p is also an array of two int. Since it is not an int, printing it using %d gives undefined behaviour.
You would not be able to "link" ptr to p because of a type mismatch (ptr is a pointer to int, and p (as already noted) is a pointer to an array of two int. Hence the assignment ptr = p would not compile. If you are forcing it to compile (e.g. ptr = (int *)p), then ptr and p will have the same value (i.e. they will identify the same location in memory) but different type (i.e. dereferencing them interprets the contents of that memory differently).
The value (ignoring type) of p will be the address of s[0][0]. Similarly, the value of ptr will be the address of s[0][0].
As a result printf("%d\n", *ptr) will print the value of s[0][0].
When both the pointers are pointing to the same address why does one pointer (*ptr) work as expected and other (*p) does not return expected values?
*p evaluates to an int[2], an array.
Passing an int[2], an array to a function, results in passing a pointer the array's 1st element, a int*.
*ptr evaluates to an int.
Passing an int to a function, results in passing an int to a function ... :-)
By
int (*ptr)[2] ; // means int[2]<-(*ptr)
You got pointer to an array of two integers
The pointer p is now assigned the address of 1st element of row
within a for loop.
This is not correct, technically p is assigned the address of the entire int[2] block (Hint : use sizeof to verify the size).
What is the problem with printf ("%d \n", *ptr)
*ptr by itself doesn't contain a integer but it holds the address of the first element of int[2] ie *ptr itself is a pointer.
A working example would be
int main(void)
{
int i;
int s[4][2]={{0,1},{2,3},{4,5},{6,7}};
int (*ptr)[2];
for(i=0;i<4;i++)
{
ptr=&s[i];
printf("i:%d\n",i);
printf("Element 1 : %d\n",(*ptr)[0]);
printf("Element 2 : %d\n",(*ptr)[1]);
/* Replacing (*ptr)[1] with *((*ptr)+1) gives you the same
* results
*/
}
return 0;
}
Output
i:0
Element 1 : 0
Element 2 : 1
i:1
Element 1 : 2
Element 2 : 3
i:2
Element 1 : 4
Element 2 : 5
i:3
Element 1 : 6
Element 2 : 7

Learning C Pointers - Assignment is to print out addresses and the size of variables of three different arrays

I wrote the following code which works, and I can see that a pointer only takes up (I think) 4 bytes of memory; while a plain old array takes up 20 bytes. However, I am not sure entirely why it works!
When I declare my character array I had to make it a pointer, otherwise it would not compile and run. I then was able to make my character an int type pointer; but I am not sure why this works.
Why can I do this "int *ptrOfChars = arrayOfChars;" and not do this "char *ptrOfChars = arrayOfChars;" ?
Here's my code:
int main(void)
{
int i;
int arrayOfNums[] = {1,2,3,4,5};
char *arrayOfChars[] = {"hello","how","are","you","doing"};
float arrayOfFloats[] = {1.23,2.34,3.45,4.56,5.67};
int *ptrOfNums = arrayOfNums;
int *ptrOfChars = arrayOfChars;
float *ptrOfFloats = arrayOfFloats;
printf("\n\n");
printf("----- Array of Numbers -----\n");
printf("The size of this array is %d\n\n", sizeof(arrayOfNums));
for (i = 0; i < 5; i++)
{
printf("Value in the array is %d\n", *ptrOfNums);
printf("Address of pointer is %x\n", ptrOfNums++);
}
printf("\n\n");
printf("----- Array of Characters -----\n");
printf("The size of this array is %d\n\n", sizeof(*arrayOfChars));
for (i = 0; i < 5; i++)
{
printf("Value in the array is %s\n", *ptrOfChars);
printf("Address of pointer is %x\n", ptrOfChars++);
}
printf("\n\n");
printf("----- Mardi Gras -----\n");
printf("The size of this array is %d\n\n", sizeof(arrayOfFloats));
for (i = 0; i < 5; i++)
{
printf("Value in the array is %f\n", *ptrOfFloats);
printf("Address of pointer is %x\n", ptrOfFloats++);
}
system("pause");
return 0;
}
Thanks for your assistance!!
//This is an array of strings.
char *arrayOfChars[]={"hello","how","are","you","doing"};
//This is an array of characters.
char arrayOfChars[]={'h','e','l','l','o',};
Each pointer in your array char *arrayOfChars[] , points to the first character of each word.
This is all the information you need to find a word from your array.
For example to get the first word of your array you need a pointer to the first character of the string 'hello'.
Then you will find the next character and the next and so on.
h --> e --> l --> l --> o --> EndOfString.
You declares a array of pointer which is of (char *) type.
char *arrayOfChars[] = {"hello","how","are","you","doing"};
which means you have:
arrayOfChars[0] -> "hello"
arrayOfChars[1] -> "how"
arrayOfChars[2] -> "are"
arrayOfChars[3] -> "you"
arrayOfChars[4] -> "doing"
And the sizeof(arrayOfChars[0]) is 4 (4 bytes, this is the size of char * variable), the strlen(arrayOfChars[0]) is 5 (the length of the string "hello"). Hope it helps.
arrayOfChars is not a array of characters but an array of pointers to strings. Therefore, the correct definition for ptrOfChars should be:
char **ptrOfChars = arrayOfChars;
Assigning arrayOfChars to int *ptrOfChars works because in this case, the size of a pointer and of an int are both 4 bytes and therefore are identical in size. Furthermore, because C doesn't really do any strong type checking, passing the value of int as the value of a char pointer still works correctly. However, under a different memory model such as 64 bit, the size of both the pointer and of an int could be different and therefore your code wouldn't work with int *ptrOfChars.
To print the size of the array arrayOfChars, you need to use sizeof(arrayOfChars) instead of sizeof(*arrayOfChars).
Finally, the type for the values for 1.23, 2.34, etc. is double and not float. To have float, you should add a little f at the end: 1.23f, 2.34f, etc.
it is because when you will print the value of arrayOfChars it is an integer(an address of arrayOfChars[0] i.e"Hello").
and your ptrOfChars is pointing to this integer.
Why can I do this "int *ptrOfChars = arrayOfChars;" and not do this "char *ptrOfChars = arrayOfChars;" ?
Because the type of the expression arrayOfChars "decays" to type char **, not char *.
Except when it is the operand of the sizeof or unary & operators, or is a string literal being used to initialize another array in a declaration, an expression of type "N-element array of T" will be converted ("decay") to an expression of type "pointer to T", and the value of the expression is the address of the first element of the array.
So, given the declaration:
char *arrayOfChars[] = {"hello","how","are","you","doing"};
the expression arrayOfChars has type "5-element array of char *" (each of the string literals is also an array expression, and also subject to the conversion rule mentioned above). If arrayOfChars appears in an expression where it is not the operand of the sizeof or unary * operators, it will be converted to an expression of type "pointer to char *", or char **.
I would have expected the compiler to complain about initializing an int * with a char ** expression.
Finally, use the %p conversion specifier to print out pointer values:
printf( "address of arrayOfChars = %p\n", (void *) arrayOfChars );
This is one of the few places where an explicit cast to void * is needed.

C assigning the address of a 2D array to a pointer

I was reading through some lecture notes that in order for a pointer to reference a 2D array, it has to be given the address of the first element.
int a[10][10];
int *p = &a[0][0];
I've never tried this, so I was curious why isn't it enough to assign the array itself to the pointer, just as we do in a 1D case.
int a[10][10];
int *p = a;
The array is kept in an uninterrupted 'line' of memory anyway, and 2D arrays only have a different type, but the same structure as 1D arrays.
By doing this
int *p = &a[0][0];
I don't see how we give the pointer any more information than by doing this
int *p = a;
Or maybe all arrays regardless of their number of dimensions have the same type, the only difference being that multidimensional arrays store their extra dimensions before their first element and we need to jump over those memory spaces which remember sizes of an array's dimensions?
First, some background:
Except when it is the operand of the sizeof or unary & operators, or is a string literal being used to initialize another array in a declaration, an expression of type "N-element array of T" will be converted ("decay") to an expression of type "pointer to T", and the value of the expression will be the address of the first element of the array.
Given the declaration
int a[10][10];
the expression a has type "10-element array of 10-element array of int". Unless this expression is the operand of the sizeof or unary & operators, it will be converted to an expression of type "pointer to 10-element array of int", or int (*)[10].
Given that declaration, all of the following are true:
Expression Type Decays to
---------- ---- ---------
a int [10][10] int (*)[10]
&a int (*)[10][10]
*a int [10] int *
a[i] int [10] int *
&a[i] int (*)[10]
*a[i] int
a[i][j] int
&a[i][j] int *
Also,
sizeof a == sizeof (int) * 10 * 10
sizeof &a == sizeof (int (*)[10][10])
sizeof *a == sizeof (int) * 10
sizeof a[i] == sizeof (int) * 10
sizeof &a[i] == sizeof (int (*)[10] )
sizeof *a[i] == sizeif (int)
sizeof a[i][j] == sizeof (int)
sizeof &a[i][j] == sizeof (int *)
Note that the different pointer types int (*)[10][10], int (*)[10], and int * don't have to be the same size or have the same representation, although on the platforms I'm familiar with they do.
The address of the first element of the array is the same as the address of the array itself; thus, all of a, &a, a[0], &a[0], and &a[0][0] will yield the same value, but the types will be different (as shown in the table above).
So, assume we add the following declarations:
int *p0 = &a[0][0]; // equivalent to int *p0 = a[0];
int (*p1)[10] = &a[0]; // equivalent to int (*p1)[10] = a;
int (*p2)[10][10] = &a;
All of p0, p1, and p2 initially have the same value, which is the address of the first element in a; however, because of the different pointer types, the results operations involving pointer arithmetic will be different. The expression p0 + 1 will yield the address of the next int object (&a[0][1]). The expression p1 + 1 will yield the address of the next 10-element array of int (&a[1][0]). And finally, the expression p2 + 1 will yield the address of the next 10-element array of 10-element array of int (effectively, &a[11][0]).
Note the types of p1 and p2; neither is a simple int *, because the expressions being used to initialize them are not that type (refer to the first table).
Note the pattern; for an array type, the simpler the expression, the more complicated the corresponding type will be. The expression a does not refer to a single int object; it refers to a 10x10 array of int objects, so when it appears in an expression, it is treated as a pointer to an array of integers, not a pointer to a single integer.
The compiler knows that "a" is a pointer to ten integers. If you don't declare the dimensions, then the compiler sees the new pointer as a pointer to an unknown number of integers. This will work in your case, but it will generate a compiler warning because the compiler sees them as incompatible pointers. The syntax for what you are trying to do (without generating a compiler warning) is:
int a[10][10];
int *p1 = &a[0][0];
int (*p2)[10] = a;
printf("p1: %p p2: %p\n", p1, p2);
One reason this is important is pointer arithmetic:
p1++; //move forward sizeof(int) bytes
p2++; //move forward sizeof(int) * 10 bytes
You understanding is close, the difference is the type information. Pointer does has its type. For example int* p, the pointer type is int*, as int a[10][10], the corresponding pointer type is int *[10][10].
In your example, p and a do point to the same address, but they're different type, which matters when perform arithmetic operation on them.
Here's an example from this URL
Suppose now that we define three pointers :
char *mychar;
short *myshort;
long *mylong;
and that we know that they point to the memory locations 1000, 2000, and 3000, respectively.
Therefore, if we write:
++mychar;
++myshort;
++mylong;
mychar, as one would expect, would contain the value 1001. But not so obviously, myshort would contain the value 2002, and mylong would contain 3004, even though they have each been incremented only once. The reason is that, when adding one to a pointer, the pointer is made to point to the following element of the same type, and, therefore, the size in bytes of the type it points to is added to the pointer.
You are right, you can assign the array itself to the pointer:
int a[10][10] = {[0][0]=6,[0][1]=1,[1][0]=10,[1][1]=11};
int b[10][10][10] = {[0][0][0]=8,[0][0][1]=1,[0][1][0]=10,[1][0][0]=100};
int *p, *q, *r, *s;
p = &a[0][0];
q = a; // what you are saying
r = &b[0][0][0];
s = b; // what you are saying
printf("p= %p,*p= %d\n",p,*p);
printf("q= %p,*q= %d\n",q,*q);
printf("r= %p,*r= %d\n",r,*r);
printf("s= %p,*s= %d\n",s,*s);
And the output is:
p= 0xbfdd2eb0,*p= 6
q= 0xbfdd2eb0,*q= 6
r= 0xbfdd3040,*r= 8
s= 0xbfdd3040,*s= 8
They point to the same address, regardless of the dimension of the matrix. So, what you are saying is right.
Well in 2D array, the outcome of *a and a is the same, they all point to the first address of this 2D array!
But if you want to define a pointer to point to this array, you could use int (*ptr)[10] for example.
You are right, 1D and 2D share the same structure, but 2D has some additional manipulation on pointers like above.
So all in all, in 2D array, a, *a and &a[0][0] prints the same address, but their usages may vary.
Like this:
#include<stdio.h>
int main() {
int a[10][10];
int *pa1 = &a[0][0];
int *pa2 = *a;
printf("pa1 is %p\n", pa1);
printf("pa2 is %p\n", pa2);
printf("Address of a is %p\n", a);
// pointer to array
int (*pa3)[10];
pa3 = a;
printf("pa3 is %p\n", pa3);
return 0;
}
They print the same address.

address of pointer to C multi-dimension array

Question from code below:
#include <stdio.h>
int main(int argc,char *arg[]){
if (argc>2){
int m=atoi(arg[1]);
int n=atoi(arg[2]);
int a[m][n];
int (*p)[m][n]=&a;
printf("p : %p, *p : %p, **p : %p\n",p,*p,**p);
}
return 0;
}
Main Env: gcc version 4.6.3 (Ubuntu/Linaro 4.6.3-1ubuntu5) x86-64
gcc main.c
./a.out 2 4
output:
p : 0xbfea7ef0, *p : 0xbfea7ef0, **p : 0xbfea7ef0
Question is why p == *p == **p. I think this may be because a is an array, kind of constant pointer which address is something specific, and this involves some implementation detail of gcc.
p is a pointer to an array with dimensions [m][n]. The value of that pointer is the address of a, so printing p gets you the address of a.
*p is an array with dimensions [m][n]. The "value" of this as a pointer is a pointer to the first element of the array, which is a[0]. This is the same address as a.
**p is an array with dimensions [n]. The value of this pointer is a pointer to the first element of the array, which is a[0][0]. This is the same address as a again.
The observed behaviour is the same for fixed-size arrays and variably-modified arrays:
#include <stdio.h>
int main(void)
{
enum { m = 3, n = 4 };
int a[m][n];
int (*p)[m][n] = &a;
printf("p : %p, *p : %p, **p : %p\n", p, *p, **p);
return(0);
}
On my machine, this produced:
p : 0x7fff6c542520, *p : 0x7fff6c542520, **p : 0x7fff6c542520
Of course, p is a pointer to a 2D array in both programs (and I shan't add the 'in both programs' qualifier again, even though it applies). When you print p, you get the address of the array that's assigned to it, which is the address of a. Because p is a pointer to a 2D array, *p 'is' the 2D array, but an array reference becomes a pointer to its first element in most situations, so *p is a pointer to a[0], which is the same memory location as a references. Similarly, **p 'is' a 1D array, but similarly, **p is a pointer to a[0][0], which is also the same memory location as a references. So, the three values are supposed to be the same, and the compiler gets it right.
That's not easy reading, but then, neither is the C that it is trying to explain.
Here's a minor variation on the original program which illustrates the sizes of the different objects pointed at by p, *p and **p:
#include <stdio.h>
int main(void)
{
enum { m = 3, n = 4 };
int a[m][n];
int (*p)[m][n]=&a;
printf("p+0 : %p, (*p)+0 : %p, (**p) + 0 : %p\n",
(void *)(p+0), (void *)((*p)+0), (void *)((**p)+0));
printf("p+1 : %p, (*p)+1 : %p, (**p) + 1 : %p\n",
(void *)(p+1), (void *)((*p)+1), (void *)((**p)+1));
return(0);
}
Strictly, the %p conversion specification should be given a void *; the casts here enforce that. The original code is, officially, a bit sloppy, though there are few machines where it would matter.
The output from this was:
p+0 : 0x7fff63453520, (*p)+0 : 0x7fff63453520, (**p) + 0 : 0x7fff63453520
p+1 : 0x7fff63453550, (*p)+1 : 0x7fff63453530, (**p) + 1 : 0x7fff63453524
Note how the sizes of the objects pointed at are different, as represented by the +1 version:
sizeof(*p) = 0x30
sizeof(**p) = 0x10
sizeof(***p) = 0x04

Resources