A[0]
和 A[1]
显然是指数,毫无疑问,要指向各个数组。但是A
不应该是指向A[0]
的指针,因为在GCC中编译printf("%d", A)
会导致以下错误:
格式
%d
期望类型int
的参数,但参数2具有类型int *
如果A
不是指针,那么为什么使用指针定义2D矩阵时会考虑指针。
此外,printf("%d", *(A+1)[0]);
的工作非常好,暗示A
被渲染为指针。如果是这种情况,printf("%d", A)
应该打印A[0]
的地址,但显示汇编错误。
这个问题归结为是否是指针,而不是不是。查看此问题:数组是指针吗?
当您使用
时int arr = {1, 2, 3, 4};
int *p = arr;
ARR从INT数组转换为指针转换为INT。它和做的一样。
int *p = &arr[0]
也发生了同样的事情 printf("%d", A)
这就是为什么编译器会给您信息的原因,但这可能会令人困惑,并可能导致人们认为指针和数组确实是相同的。
有许多不同的方法来创建int
的所谓 2D矩阵,每个矩阵定义了非常不同的对象类型:
-
作为
int
的数组数组:int A[ROWS][COLS] = { 0 };
-
作为
int
数组的一系列指针:int *A[ROWS]; for (int i = 0; i < ROWS; i++) A[i] = calloc(sizeof(int), COLS);
-
作为
int
数组数组的指针:int (*A)[COLS] = calloc(sizeof(*A), ROWS);
-
作为指向
int
阵列的一系列指针的指针:int **A = calloc(sizeof(*A), ROWS); for (int i = 0; i < ROWS; i++) A[i] = calloc(sizeof(int), COLS);
在所有情况下,访问矩阵元素的语法都是相同的: A[row][col]
或任何等效指针符号变体:
*(*(A + row) + col)
*(A[row] + col)
(*(A + row))[col]
在所有情况下,A
和A[row]
都可以在预期指针的情况在表达式上下文中使用(作为sizeof
的参数除外(,例如将作为参数传递给printf
。
用printf
打印指针值需要%p
转换格式。
%d
期望的int
与指针不同,可能具有不同的尺寸,并且可能以不同的方式传递给printf
,所有这些都会导致不确定的行为。编译器对此发出非常有用的警告。最好用尽可能多的警告配置编译器来发现愚蠢的错误。这些警告有时很难理解,但几乎总是表明需要修复的事情。
您可以使用printf("%p", (void*)A)
等效于printf("%p", (void*)&A[0])
和printf("%p", (void*)A[0])
,等效于printf("%p", (void*)&A[0][0])
。所有4个都应打印相同的地址。