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]
的地址,但是会显示编译错误。
答案 0 :(得分:1)
这个问题归结为数组是否是指针,情况并非如此。看到以下问题:Arrays are Pointers?。
使用时
int arr = {1, 2, 3, 4};
int *p = arr;
arr从一个int数组转换为一个指向int的指针。 和做一样。
int *p = &arr[0]
同样的事情发生
printf("%d", A)
这就是为什么编译器会向您显示消息的原因,但这可能会造成混淆,并可能导致人们认为指针和数组确实相同。
答案 1 :(得分:1)
创建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]
,或任何等效的 pointer表示法变体:
*(*(A + row) + col)
*(A[row] + col)
(*(A + row))[col]
在所有情况下,A
和A[row]
都可以用于需要使用指针的地方,要么是因为它们确实是指针(情况3和4),要么是因为数组(情况1和2)衰减了指向在表达式上下文中使用时指向其第一个元素的指针(除了作为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个都应打印相同的地址。