不是A [m] [n]中的A指针(当我们使用指针定义二维矩阵时类似)

时间:2019-05-01 13:31:28

标签: c arrays pointers

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]的地址,但是会显示编译错误。

2 个答案:

答案 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矩阵的方法有很多,每种方法定义了非常不同的对象类型:

  1. 作为int的数组的数组:

    int A[ROWS][COLS] = { 0 };
    
  2. 作为指向int数组的指针的数组:

    int *A[ROWS];
    for (int i = 0; i < ROWS; i++)
        A[i] = calloc(sizeof(int), COLS);
    
  3. 作为指向int的数组的指针:

    int (*A)[COLS] = calloc(sizeof(*A), ROWS);
    
  4. 作为指向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]

在所有情况下,AA[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个都应打印相同的地址。