首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >理解C++中指向数组的双指针

理解C++中指向数组的双指针
EN

Stack Overflow用户
提问于 2021-03-30 11:28:24
回答 4查看 93关注 0票数 0

我已经学习C语言几个月了,我遇到了一个问题,如下所示。

代码语言:javascript
复制
#include <stdio.h>

int main() {
    int a[2][2] = {{1,2}, {3,4}};
    int (**p)[2] = &a;

    for (int i=0; i<2; ++i) {
        for (int j=0; j<2; ++j) {
            printf("%d %u\n", a[i][j], (*(a+i) + j));
        }
    }

    for (int i=0; i<4; ++i) {
        printf("%d %u\n", *(*p + i), (*p + i));
    }

    printf("%u\n", p);
    printf("%u\n", p+1);
    printf("%u\n", p+2);
    printf("%u\n", p+3);
    printf("%u\n", *p);
    printf("%u\n", *p+1);
    printf("%u\n", *p+2);
    printf("%u\n", *p+3);
    puts("");
}

我在机器上得到的输出如下所示:

代码语言:javascript
复制
1 3751802992
2 3751802996
3 3751803000
4 3751803004
1 1
9 9
17 17
25 25
3751802992
3751803000
3751803008
3751803016
1
9
17
25

我知道输出的前四行,其中打印了2D数组的元素及其各自的地址,但我完全不知道其他输出是如何发生的。

我检查了一个在线IDE,在那里我也得到了相同的输出,除了明显不同的地址。我知道int (**p)2是一个(int *)2数据类型,它是a2不可比拟的指针类型。但是我仍然想知道p指针是如何工作的。

有没有人能告诉我这是怎么回事?我一直在热切地等待着了解代码输出背后的逻辑。对于长代码片段和长输出序列,我感到非常抱歉。提前谢谢。

注意:我知道代码产生了很多警告,但我想了解关于p的核心思想。

EN

回答 4

Stack Overflow用户

发布于 2021-03-30 12:03:08

这段代码的问题就从这里开始:

代码语言:javascript
复制
int main() {
    int a[2][2] = {{1,2}, {3,4}};
    int (**p)[2] = &a; // <-- Invalid conversion, undefined behaviour

    // warning: incompatible pointer types initializing 'int (**)[2]' with an expression of type 'int (*)[2][2]' [-Wincompatible-pointer-types]

    // ... Everything past here is undefined behaviour
}

int**和您试图转换的内容之间有一个巨大的差异,这个差异足够大,以至于这种转换是不可能的。

具体地说,int**指的是一种结构,其中它是一个int*数组或指针。把int[2]当做指针来对待将会是一团乱麻。这些代码中的任何一个甚至是半成品都很难解释。这是编译器试图在最坏的情况下做到最好。

票数 1
EN

Stack Overflow用户

发布于 2021-03-30 12:12:22

我引入了宏LEN来计算数组大小,而不是硬拷贝魔术数字,修复了p的声明,在打印有符号值时将无符号格式%u更改为有符号%d,最后一次循环,我确定您试图打印的第二件事是什么,所以省略了它,并且打印语句的最后一段是指针,因此在循环中使用%p而不是重复代码:

代码语言:javascript
复制
#include <stdio.h>

#define LEN(a) sizeof(a) / sizeof(*a)

int main() {
    int a[2][2] = {{1,2}, {3,4}};
    int (*p)[2] = a;

    for (int i=0; i < LEN(a); i++) {
        for (int j = 0; j < LEN(*a); j++) {
            printf("%d %d\n", a[i][j], *(*(a + i) + j));
        }
    }

    for (int i=0; i < LEN(a) * LEN(*a); i++) {
        printf("%d\n", *(*p + i));
    }

    for(int i = 0; i < LEN(a) * LEN(*a); i++) {
        printf("%p\n", p + i);
    }

    for(int i = 0; i < LEN(a) * LEN(*a); i++) {
        printf("%p\n", (void *) *(p + i));
    }

    puts("");
}
票数 1
EN

Stack Overflow用户

发布于 2021-03-30 22:09:20

这是一个问题:

代码语言:javascript
复制
int (**p)[2] = &a; // int (**)[2] = int (*)[2][2]

&a的类型是int (*)[2][2],而不是int (**)[2]。你的指针声明应该是

代码语言:javascript
复制
int (*p)[2][2] = &a;

除非是指针sizeof运算符或一元& 运算符的操作数,或者是用于在声明中初始化字符数组的字符串文字,否则类型为“N- of T”的表达式将被转换为“指向T的指针”类型的表达式,并且表达式的值将是数组的第一个元素的地址。

表达式a从类型"2-element array of 2-element array of int“(int [2][2])”衰减“到"pointer to 2-element array of int”(int (*)[2])。但是,由于a是一元&运算符的操作数,因此不会发生转换,因此&a具有类型"pointer to 2-element array of 2-element array of int“(int (*)[2][2])。因此,

代码语言:javascript
复制
   p  == &a
 (*p) ==  a

  (*p) + i  ==   a + i  == &(*p)[i] == &a[i]
*((*p) + i) == *(a + i) ==  (*p)[i] ==  a[i]

  *((*p) + i) + j  ==   *(a + i) + j  == &(*p)[i][j] == &a[i][j]
*(*((*p) + i) + j) == *(*(a + i) + j) ==  (*p)[i][j] ==  a[i][j]
票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/66864404

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档