简体   繁体   中英

Multidimensional arrays: don't the pointers point to their own addresses?

I'm a student learning C, trying to wrap my head around something.

Let's say you have some multidimensional array int multi[2][2] . The value of multi will be a pointer to the address of multi[0] . For simplicity, let's say that address is 1000. Dereferencing multi[0] extracts another address, this address the address of multi[0][0] . Dereferencing that, in turn, gets us the value (or returns the address for assignment if on the left side.)

Now, multi + 1 returns the address of the second pointer. Let's say that we have 4 byte ints (of which there are two per nested array), so the address returned by multi + 1 will be 1008. This address will contain the address of multi[1][0] , which will be 1008.

So here I see a pattern: doesn't this mean that the address in multi[0] , multi[1] , and so forth, contains a pointer to its own address ?

Arrays and pointers are different. This topic is often presented poorly in books.

In the case of int multi[2][2] , this is a block of 4 contiguous ints. There are no pointers involved. C's type system divides this block up into two sub-arrays, each containing 2 ints.

These expressions: multi , multi[0] denote arrays. When you use an expression that denotes an array, in a context other than sizeof or & , then a conversion is performed, and the result of that conversion is a pointer to the first element of the array.

This pointer is an rvalue , ie it has the same sort of status as x + y : it's a value you can work with, but it doesn't consume any storage (at least, it's not stored as part of the array); and you can't use the & operator on it.

The value of multi will be a pointer to the address of multi[0]

If multi , which is an array, is used in an expression, it is converted to a pointer to multi[0] , the value of which is the address of multi[0] . An array, when used in an expression, is always converted to a pointer to its first element ... thus arrays in C aren't first class objects and cannot be passed to functions (only their addresses can) or assigned ( memcpy is used to copy arrays).

Dereferencing multi[0] extracts another address, this address the address of multi[0][0]

There's no "extraction". dereferencing multi[0] yields an array, which is converted to a pointer to its first element. The value of this pointer is the address of multi[0][0] . All of these addresses have the same value, because they point to exactly the same place in memory ... the first of four int s.

Now, multi + 1 returns the address of the second pointer.

Again, there is no pointer in memory . multi + 1 refers to an array ... the second of two arrays of two int s. Using that array in an expression converts it to a pointer to its first element, multi[1][0] .

Let's say that we have 4 byte ints (of which there are three per nested array), so the address returned by multi + 1 will be 1012.

Er, you declared int multi[2][2] , which is two arrays each of which contains two arrays. So multi + 1 is 1008.

This address will contain the address of multi[1][0], which will be 1012.

It makes no sense to talk about addresses containing addresses. pointers contain addresses, but we have no pointers in memory here, we only have int s. multi[1][0] is an int and its address is 1008. multi[1] is an array of int s and its address is also 1008 ... of course, because its address is the same as the address of its first element.

So here I see a pattern: doesn't this mean that the address in multi[0], multi[1], and so forth, contains a pointer to its own address?

There are no addresses in multi[0] and multi[1] , there are arrays (of int s). arrays have addresses, but in this case they don't contain addresses. The way to "see a pattern" is to think in terms of what's in memory. Here, you simply have a block of 4 int s -- two arrays of two int s each; arrays have no overhead or other extraneous content in C, they just have the data ... what you declare is what you get. The array is an abstraction , a grouping of items determined by its type and size, which exist only at compile-time and in the mind of the programmer. Thus, multi[0] contains an array , in the abstract model of a C program, but all there is in memory is four int s, the first two of which comprise that array.

The situation would be different with

int* multi[2];

There you have an array of two pointers to int ; each pointer will point to an array of int s (once you set it to the address of an array of int s, usually obtained from malloc ). Once you allocate memory for the subarrays and assign the two pointers, you can use this multi much the way you use the multi above, but the type, size, and memory layout of multi[0] and multi[1] are quite different in the two cases.

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