简体   繁体   中英

What is the difference between these two statements?

I have these two statements:

printf("%u",a+1);

and

printf("%u",(int *)a+1);

Actually I was working on this code when I came across this confusion.

#include<stdio.h>

int main()
{
  int a[2][2]={1,2,3,4};
  int i,j;
  int *p[] = { (int*)a, (int*)a+1, (int*)a+2 };
  for(i=0; i<2; i++){
    for(j=0; j<2; j++){
      printf("%d %d %d %d",* (*(p+i)+j), *(*(j+p)+i), *(*(i+p)+j), *(*(p+j)+i));
    }
  }
  return 0; 
}

Output:

1 1 1 1
2 2 2 2
2 2 2 2
3 3 3 3

In order to understand the output of the above program I came to know that the difference that's making this output can be solved if I know the difference between above two statements.

My current understanding: (a+1) will give me the address of 2nd element of array. In this case a 2-d array can be visualized as 2 1-d arrays, each with 2 elements. So (a+1) will give me the address of a[1][0] , but then why is (int *)a+1 giving me the address of a[0][1] ?

Please explain the difference and the output of the program.

Thanks.

The idiom (int*)a+1 is interpreted as ((int*)a) + 1) . That is, the cast takes precedence over the addition. So this evaluates to (int*) a) , which is the address of the array as ptr-to-int, offset by 1, which returns the second element in the array ( 2 ).

Two critical rules of programming:

Rule 1: When you write code, make the layout reflect the functionality.
Rule 2: When you read code, read the functionality, not the layout. (Corollary: debug the code , not the comments .)

Conceptually, when you declare

int a[2][2]={1,2,3,4};

you envision a 2 dimensional array like this:

  1 2
  3 4

But C actually stores the data in a contiguous block of memory, like this:

  1 2 3 4

It "remembers" that the data represents a 2×2 array when it calculates the indices. But when you cast a from its original type to int * , you're telling the compiler to forget about its original declaration, effectively losing its 2-dimensionality and becoming a simple vector of int s.

Here's how to understand the declaration of p :

int *p[] = { (int*) a,  (int*) a+1,     (int*) a+2 };     // As written
int *p[] = { (int*) a,  ((int*) a) + 1, ((int*) a) + 2 }; // As interpreted
int *p[] = { &a[0][0],  &a[0][1],       &a[1][0] };       // Resulting values

From this, you can see that p is a one-dimensional array of vectors:

p[0] = { 1, 2, 3 }
p[1] = { 2, 3 }
p[2] = { 3 }

If you recognize that (p+i) == (i+p) , then the last two items are the same as the first two in the line

printf("%d %d %d %d\n",* (*(p+i)+j), *(*(j+p)+i), *(*(i+p)+j), *(*(p+j)+i));

which is equivalent to this:

printf("%d %d %d %d\n", p[i+j], p[j+i], p[i+j], p[j+i]);

It's interesting to note that, since the following are all equivalent:

a[i]
*(a+i)
*(i+a)

then it's perfectly legal to write i[a] to represent the same value. In other words, the compiler allows you to write

printf("%d %d %d %d\n", p[i], i[p], p[1], 1[p]);

Of course, your tech lead had better not allow you to write that. If you write that in my group, you're fired. ;-)

None, both produce undefined behavior. The correct format to print a pointer value is %p . Cast your pointer to void* when sending it to printf .

Multidimensional C arrays behave like single-dimensional arrays laid out next to each other. So if you cast a (normally (int **) ) to (int *) you get the same thing you would get from a[0] . Thus (int *) a + 1 is &a[0][1] . Otherwise your understanding is correct, which is why a + 1 gets you &a[1][0] .

(This behavior is specified by the standard; but that does not make it good programming practice.)

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM