c - Inconsistency in using pointer to an array and address of an array directly -


this code sample prints array correctly.

int b[2] = {1, 2}; int *c = &b; int  i, j,k = 0; (i = 0;i < 2; i++) {     printf("%d ", *(c+i)); } 

while 1 prints 2 garbage values.

int b[2] = {1, 2}; int  i, j,k = 0; (i = 0;i < 2; i++) {     printf("%d ", *(&b+i)); } 

why 2 code samples behaving differently?

the declaration:

int b[2] = {1, 2}; 

creates array of 2 int values 1, 2.
suppose in system size of int 4-bytes, array b[] should stored in memory follows:

first ele        +----------+                      (b + 0) ---►|     1    | 0xbf5c787c  <----- &b ,    (c + 0) next ele         +----------+       (b + 1) ---►|     2    | 0xbf5c7880  <------------- (c + 1)                  +----------+                    (b + 2) ---►|     ?    | 0xbf5c7884  <----- (&b + 1) next array                    +----------+                                  ---►|     ?    | 0xbf5c7888                    +----------+               ---►|     ?    | 0xbf5c788c  <----- (&b + 2) next array                    +----------+                    ---►|     ?    | 0xbf5c7890                  +----------+                 ? means garbage value b[] array in memory 0xbf5c787c 0xbf5c7880   each cell 4 bytes  

in above diagram memory cells value ? means garbage values , not allocated (memory 0xbf5c7884 not allocated in our array). values 1, 2 stored in memory @ address 0xbf5c787c , 0xbf5c7880, allocated in array b[].

let's instead of printing values, print addresses of memory access in code using (c + i) , (&b + i), consider following program:

#include<stdio.h> int main(){   int b[2] = {1, 2};    int  = 0;   int *c = &b; //give warning: "assignment incompatible pointer type"    printf("\n c address: ");  // outputs correct values    (i = 0; < 2; i++) {     printf("%p ", (void*)(c + i));   }   printf("\n b address: ");  // outputs incorrect values/ , behaving differently    (i = 0; < 2; i++) {     printf("%p ", (void*)(&b + i));  // undefined behavior    }   return 1; } 

outputs:

 c address: 0xbf5c787c 0xbf5c7880   b address: 0xbf5c787c 0xbf5c7884  

check code working @codepade
notice, (c + i) prints correct address of cells value 1, 2 hence outputs in first code correct. whereas (&b + i) prints address value not allocated array b[] (that outside of array b[]) , accessing memory gives undefined behaviour(unpredictable) @ runtime.

actually there difference between b , &b.

  • b array , type int[2], b decays int* address first element in expressions (read: some exceptions array name not decaying pointer first element?). , b + 1 points next int elements in array (notice diagram).

  • &b address of complete array , type int(*)[2], (&b + 1) points next array of type int[2] not allocated in program (notice in diagram (&b + 1) points).

to know other interesting differences between b , &b read: what sizeof(&array) return?

in first code snipe, when c = &b, assigning array's address int* (in our example 0xbf5c787c). gcc compiler statement give warning: "assignment incompatible pointer type".
because c pointer int, *(c + i) prints integer stored @ address (c + i). i = 1 value (c + 1) points second element in array (in our example @ 0xbf5c7880) hence *(c + 1) prints 2 correctly.

regarding assignment int *c = &b; in first code highly suggest read @andreyt's answer below. correct , simple way access array elements using pointer follows:

int b[2] = {1, 2}; int *c = b;   // removed &, `c` pointer int   int i; (i = 0; < 2; i++){     printf("%d ", *(c + i));   // printf("%d ", c[i]); // correct statement  } 

in second code, adding i &b make pointing outside allocated memory , in printf statement access memory using * dereference operator cause invalid memory access , behavior of code @ run time undefined. reason second piece of code behaving differently @ different execution.

your code compiles because syntactically correct, @ runtime accessing of unallocated memory can detected os kernel. may causes os kernel send signal core dump process caused exception (interesting note: os detects memory right violation process -- invalid access valid memory gives: sigsegv, , access invalid address gives: sigbus). in worth case program may execute without failure , produce garbage results.

regarding second code, correct way print array using 'pointer array' below:

#include<stdio.h> int main(){   int b[2] = {1, 2};    int  i;   int (*c)[2] = &b;   // `c` pointer int array of size 2   for(i = 0; < 2; i++){      printf(" b[%d] = (*c)[%d] = %d\n", i, i, (*c)[i]); // notice (*c)[i]   }   return 1; } 

output:

b[0] = (*c)[0] = 1 b[1] = (*c)[1] = 2   

check @codepade. point notice parenthesis around *c needed precedence of [] operator higher * dereference operator (whereas if use pointer int don't need parentheses in above code).


Comments