我已经学习C语言几个月了,我遇到了一个问题,如下所示。
#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("");
}我在机器上得到的输出如下所示:
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的核心思想。
发布于 2021-03-30 12:03:08
这段代码的问题就从这里开始:
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]当做指针来对待将会是一团乱麻。这些代码中的任何一个甚至是半成品都很难解释。这是编译器试图在最坏的情况下做到最好。
发布于 2021-03-30 12:12:22
我引入了宏LEN来计算数组大小,而不是硬拷贝魔术数字,修复了p的声明,在打印有符号值时将无符号格式%u更改为有符号%d,最后一次循环,我确定您试图打印的第二件事是什么,所以省略了它,并且打印语句的最后一段是指针,因此在循环中使用%p而不是重复代码:
#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("");
}发布于 2021-03-30 22:09:20
这是一个问题:
int (**p)[2] = &a; // int (**)[2] = int (*)[2][2]&a的类型是int (*)[2][2],而不是int (**)[2]。你的指针声明应该是
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])。因此,
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]https://stackoverflow.com/questions/66864404
复制相似问题