我目前正在研究c编程语言的多维数组和指针。
我被问到以下问题
假设您有以下声明:
int grid[30][100];.
以两种方式表示网格[22] [0]的地址。
作者提供了以下答案
&grid[22][0] or grid[22]
我想出了
//notice for the second answer, I placed an address operator & at the front
&grid[22][0] or &grid[22]
我测试了以下代码
#include <stdio.h>
int main(void){
int ar[2][3] = {
{11, 22, 33},
{44, 55, 66}
};
printf("%p\n", &ar[2][0]);
printf("%p\n", ar[2]);
printf("%p\n", &ar[2]);
return 0;
}
并且所有三个表单都打印了相同的值
0062ff30
0062ff30
0062ff30
作者的答案grid[22]
和答案&grid[22]
是否相同?它们怎么可能相同?
答案 0 :(得分:1)
首先,如果您使用%p
,则必须将值转换为(void*)
,
因为%p
期望a期望一个无效指针
printf("%p\n", (void*) &ar[2][0]);
printf("%p\n", (void*) ar[2]);
printf("%p\n", (void*) &ar[2]);
他们都有相同的地址(因为他们都在同一个地方 记忆)但他们的表达方式有不同的类型:
&ar[2][0];
是int*
(指向int
)
ar[2];
是int[3]
(维度3的int
数组),但在printf
它衰变成
一个int*
然后由于演员而变为void*
。
&ar[2];
是int (*)[3]
(指向int[3]
的指针,int
维度2的数组。
当您使用int[3]
数组时,您可以看到sizeof
是一个数组
不会腐烂成指针:
printf("sizeof &ar[2][0]: %zu\n", sizeof &ar[2][0]);
printf("sizeof ar[2]: %zu\n", sizeof ar[2]);
printf("sizeof &ar[2]: %zu\n", sizeof &ar[2]);
打印(在我的系统上,x86_64
):
sizeof &ar[2][0]: 8 (size of an pointer)
sizeof ar[2]: 12 (size of an array `int[3]`)
sizeof &ar[2]: 8 (size of a pointer)
如果你有这个功能
void foo(int *x)
{
(void) x; // to silence -Wall warnings
}
然后foo(&ar[2][0])
很好,foo(ar[2])
也很好,因为它会衰减
成指针。但是foo(&ar[2])
并不好,你会得到:
a.c: In function ‘main’:
a.c:21:6: warning: passing argument 1 of ‘foo’ from incompatible pointer type [-Wincompatible-pointer-types]
foo(&ar[2]);
^
a.c:3:6: note: expected ‘int *’ but argument is of type ‘int (*)[3]’
void foo(int *x)
^~~
然而
void bar(int (*x)[3])
{
(void) x;
}
bar(&ar[2])
没问题。
请记住,如果你用任何一个打印值/访问内存
这些表达式,您将访问超出范围的数据。 ar
应该是
int ar[3][3] = {
{11, 22, 33},
{44, 55, 66},
{77, 88, 99}
};