[英]multi dimensional array in c
Please explain the output of first and last printf
statements. 请解释第一个和最后一个
printf
语句的输出。 I think they should give the same output. 我认为他们应该提供相同的输出。
int main()
{
char arr[5][7][6];
char (*p)[5][7][6] = &arr;
printf("%d\n", (&arr + 1) - &arr);
printf("%d\n", (char *)(&arr + 1) - (char *)&arr);
printf("%d\n", (unsigned)(arr + 1) - (unsigned)arr);
printf("%d\n", (unsigned)(p + 1) - (unsigned)p);
return 0;
}
Output: 输出:
1
210
42
210
Lets see the memory layout first: 首先让我们看一下内存布局:
char arr[5][7][6];
here arr
is a array of arrays of arrays. 这里
arr
是一个由数组组成的数组。
It will be laid out into memory like following: 它会像下面这样布置到内存中:
+--------------+
| | arr[0]
+--------------+
| | arr[1]
+--------------+
| | arr[2]
+--------------+
| | arr[3]
+--------------+
etc.
Now arr[i]
is a array of arrays of char
. 现在,
arr[i]
是char
数组的数组。
So a[i]
will be like 所以
a[i]
就像
+--------------+ a[i][0]
| |
+--------------+
| | a[i][1]
+--------------+
| | a[i][2]
+--------------+
| | a[i][3]
+--------------+
etc
Now arr[i][j]
is a array of chars
. 现在
arr[i][j]
是一个chars
数组。
So 所以
+--------------+
| | arr[i][j][0]
+--------------+
| | arr[i][j][1]
+--------------+
| | arr[i][j][2]
+--------------+
etc.
Compiler will make an entry in its symbol table with name arr
and with the address of its first block and also keep track of the total size (5*6*7 = 210 bytes). 编译器将在符号表中使用名称
arr
和其第一个块的地址进行输入,并跟踪总大小(5 * 6 * 7 = 210字节)。
Now the expression 现在表达
printf("%d\n", (&arr + 1) - &arr);
Its a pointer arithmetic. 它是一个指针算法。 So it will bound to type of every symbols.
因此它将绑定到每个符号的类型。
Lets see this in action. 让我们来看看这一点。
(gdb) p &arr
$1 = (char (*)[5][7][6]) 0x7fffffffe160
You see the type of arr
is pointer char (*)[5][6][7]
您会看到
arr
的类型是指针char (*)[5][6][7]
In other words its pointer to a array of arrays of arrays. 换句话说,它的指针指向数组的数组。 Pointer arithmetic actually do relates to the type the pointer is pointed to.
指针算术实际上与指针所指向的类型有关。 So its important what is the size of the type.
因此重要的是类型的大小。
(gdb) p sizeof(char [5][7][6])
$2 = 210
So any pointer to the type char [5][6][7]
will be incremented or decremented like follows: 因此,指向
char [5][6][7]
类型的任何指针都将按以下方式递增或递减:
&arr+1 => 0x7fffffffe160 +0xd2 => 0x7fffffffe232
and (&arr + 1) - &arr => 0x7fffffffe232 - 0x7fffffffe160=> 0xd2
和
(&arr + 1) - &arr => 0x7fffffffe232 - 0x7fffffffe160=> 0xd2
Now it returns actually 0xd2 . 现在,它实际上返回0xd2 。 but for pointer arithmetic it means
1*sizeof(char [5][7][6]) => 1
但是对于指针算术来说,它意味着
1*sizeof(char [5][7][6]) => 1
Pointer arithmetic returns the number of sizeof(type)
instead of actual byte offset. 指针算术返回
number of sizeof(type)
的number of sizeof(type)
而不是实际的字节偏移量。
You are getting correct result for 您正在得到正确的结果
printf("%d\n", (char *)(&arr + 1) - (char *)&arr);
Because of the casting you are making it a char pointer. 由于进行了强制转换,因此您将其变成了char指针。 So the pointer arithmetic will use unit
sizeof(char)
which is of 1 byte size. 因此,指针算法将使用1字节大小的unit
sizeof(char)
。 And hence the output will be 210. 因此输出将为210。
printf("%d\\n", (unsigned)(arr + 1) - (unsigned)arr);
Here arr
in a expression will decay to type char (*)[7][6]
So its a pointer to a two dimensional array. 在这里,表达式中的
arr
将衰减为char (*)[7][6]
因此它是指向二维数组的指针。 The type its pointing to has a size 6*7 = 42. Thats what you are getting as result. 其指向的类型的大小为6 * 7 =42。这就是结果。
printf("%d\\n", (unsigned)(p + 1) - (unsigned)p); printf(“%d \\ n”,(unsigned)(p +1)-(unsigned)p);
Here, p+1 - p
will result in pointer arithmetic 1 * sizeof(char(*)[5][6][7])
. 在这里,
p+1 - p
将导致指针算术运算1 * sizeof(char(*)[5][6][7])
。 So in pointer arithmetic, it should return 1. But because of your casting the results of to unsigned , it will abandon pointer arithmetic and use integer arithmetic. 因此,在指针算术中,它应该返回1。但是由于将结果强制转换为unsigned,它将放弃指针算术,而使用整数算术。 Because of using integer arithmetic, it will treat the pointer values of large numbers, so you will get the actual byte offset.
由于使用整数算法,它将处理大数字的指针值,因此您将获得实际的字节偏移量。
They would print the same result if they were treated as pointers, but in the last printf
you're forcing them to be treated as unsigned integers by casting. 如果将它们视为指针,它们将输出相同的结果,但是在最后一个
printf
您通过强制转换将它们视为无符号整数。 Thus, p + 1
and p
are subtracted following integer arithmetic rules, as opposed to pointer arithmetic rules. 因此,与指针算术规则相反,遵循整数算术规则减去
p + 1
和p
。
To make things a little clearer: 为了使事情更清晰:
unsigned
you're telling the compiler "these are just plain numbers, nothing to see here". unsigned
您会告诉编译器“这些只是纯数字,在这里看不到任何东西”。 So the compiler treats the addresses as numbers and just subtracts them. The first takes the address of arr
and add one, then subtracts the address, the result is clearly 1. 第一个取
arr
的地址并加一个,然后减去该地址,结果显然为1。
The last one though, p
is a pointer to char [5][7][7]
, and using (*p)[x][y][z]
can be though of as p[0][x][y][z]
. 但是,最后一个
p
是指向char [5][7][7]
的指针,使用(*p)[x][y][z]
可以作为p[0][x][y][z]
。 So (p + 1)
could be thought of as p[1]
, which is 210 ( 5 * 7 * 6
) bytes away from p
. 因此
(p + 1)
可以认为是p[1]
,它与p
相距210( 5 * 7 * 6
)个字节。
If you did (((unsigned) p) + 1) - ((unsigned) p)
then that would be 1
. 如果您做了
(((unsigned) p) + 1) - ((unsigned) p)
,那将是1
。
the distance between the adresses is 1 element or 210 bytes 地址之间的距离为1个元素或210个字节
The first print prints the number of elements The last - the number of bytes 第一个打印输出元素的数量最后一个-字节数
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.