【问题标题】:multidimensional array, different ways to represent address of grid[22][0]多维数组,grid[22][0]地址的不同表示方式
【发布时间】:2018-03-07 00:16:36
【问题描述】:

我目前正在研究c编程语言的多维数组和指针。

我被问到以下问题

假设你有以下声明:

int grid[30][100];.

grid[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] 和我的答案&amp;grid[22] 是否相同?它们怎么可能相等?

【问题讨论】:

  • 地址相等,数据类型不相等。 &amp;ar[2][0]int*ar[2] 衰减为 int*&amp;ar[2]int (*)[3]

标签: c arrays pointers multidimensional-array


【解决方案1】:

首先,如果你使用%p,那么你必须将值转换为(void*), 因为%p 需要一个空指针

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 的数组)。

当您使用 sizeof 时,您可以看到 int[3] 是一个数组 不衰减为指针:

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(&amp;ar[2][0]) 很好,foo(ar[2]) 也很好,因为它会衰减 成一个指针。但是foo(&amp;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(&amp;ar[2]) 很好。

请记住,如果您使用任何一种打印值/访问内存 这些表达式,您将越界访问数据。 ar 应该是

int ar[3][3] = {
    {11, 22, 33},
    {44, 55, 66},
    {77, 88, 99}
};

【讨论】:

  • 将任何指针类型分配给 void* 是合法的;无需为 printf() 强制转换。
  • @LeeDanielCrocker 我从其他高级用户那里多次看到此建议,并且手册页状态为p The void * pointer argument is printed in hexadecimal...,所以我重复了一遍。
  • 演员阵容肯定没有问题,只是额外打字。
  • 如果代码 100% 正确,我不介意额外的输入,如果演员表很长,那么我可能会忽略它。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2023-04-07
  • 1970-01-01
  • 2011-01-01
  • 1970-01-01
  • 2014-03-23
  • 1970-01-01
相关资源
最近更新 更多