开发者

In C, why does (int*)&x[k] work as well as (int*)x[k] for a 2-D array x?

In the following code

 int x[2][3] = {{1,2,3},{4,5,6}};
 int* y1 = (int*)x[1];
 int* y2 = (int*)&x[1];

 int i;
 for(i=0; i < 3 ; i++)
 {
  printf("%i %i\n",y1[i],y2[i]);
}

why do y1 and y2 point to the same data?

I would think that x[1] is a pointer to the second row of data, so y1 should be the correct way to access it. The expression &x[1] is getting the address of the pointer to the second row of data开发者_如何学Python, so why does y2 even work?


Given the declaration

int x[2][3] = {{1,2,3},{4,5,6}};

the type of the expression x[1] is "3-element array of int". Unless an array expression is an operand of the sizeof or & address-of operator, or is a string literal being used to initialize another array in a declaration, the type of the expression is converted to "pointer to T" and the value of the expression is the address of the first element of the array.

Therefore, in the declaration

int *y1 = (int *) x[1];

the cast is unnecessary; x[1] will automatically be converted to type int *, and y1 will point to x[1][0].

In the declaration

int *y2 = (int *) &x[1];

the array expression x[1] is an operand of the address-of & operator, so it isn't automatically converted to type int *. The type of the expression &x[1] is "pointer to 3-element array of int", or int (*)[3]. The cast is necessary in this case, since you can't implicitly convert a pointer to an array of T to pointer to T. However, it's probably not what you want to do; converting a pointer to an array to a pointer to a scalar will probably lead to confusion on somebody's part.

Note that x[1] and &x[1] yield the same value (the address of the first element in the array is the same as the address of the array itself), but the types are different, which will matter for things like the ++ and -- operators.

If you want to avoid the casts, rewrite those declaration as

int *y1      =  x[1];
int (*y2)[3] = &x[1];


Well, x[1] is an array, not a pointer. The funky detail here is that address of the array is the array itself :), so to say, as in:

int a[10] = {0};
assert(( int* )a == ( int* )&a);

Edit 0:

To answer your question in the comment: A line like int a[XXX]; reserves a chunk of memory of size sizeof( int ) * XXX. Every time you use a to access that memory, a is replaced with the address of the first element. The compiler knows that address (or at least the offset of the first element from the data segment or from the stack frame). This eliminates the need for storing that address in a temporary, and then dereferencing that temporary to get to the memory itself. Compiler forms the expression with (almost) direct value of the address. Thus a here in a sense has no location to take address of, so to preserve the semantics the &a is short-circuited to just a.

On the other hand, if you pass a as a function argument it's decayed to a pointer.

All fun stuff. Get yourself this book to see more: "Expert C Programming Deep C Secrets"


Because a 2D array does not store the actual pointer of each rows. On the stack, only the address of the first element is stored. Since the x array has a fixed known size the offsets are calculated on compile time.

The expression (int*)&x[1] downgrades the array to a pointer, returning the same value.

The expression x[1] returns the address of the value 4 in memory. Using the & operator you are asking for the address of the address of the value 4, which does not make much sense in this case.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜