我尝试了以下代码
char arr[5] = {'A', 'E', 'I', 'O', 'U'};
char (*p_arr)[1] = &arr;
printf("%c\n", p_arr[0][4]); //returns 'U'
在this stackoverflow线程上,
char (*p_arr2D)[m] = &arr2D //or arr2D
也是n*m
2D数组arr2D
衰减的语法,返回指向其第一个元素的指针,即m
个元素的数组。
p_arr[0]
似乎是“反向”数组衰减,从指向数组的指针中检索2D数组。怎么会发生这种情况?在上面的代码段中,p_arr
被解释为1*5
数组(来自原始的1D数组,包含5个元素)?
答案 0 :(得分:1)
首先,行char (*p_arr)[1] = &arr;
无效C.您的编译器必须提供诊断消息。 p_arr
是指向1个char的数组的数组指针,但是您将其指定为指向5个char的数组。
至于为什么看起来你有一个2D数组 - 你不有一个 - 是因为p_arr[0]
的工作方式与任何其他指针算法一样,给你指向的项目“偏移+ 0“。哪个是阵列。然后访问数组中的第4项。
同一指针算术原理的一个简单例子是:
int a;
int* ptr = &a;
ptr[0] = whatever; // perfectly valid C
ptr[0]
保证等同于*(ptr+0)
。
正确使用数组指针应为printf("%c\n", (*p_arr)[4])
。在这种情况下,它恰好工作,但在其他情况下,您可能会调用未定义的行为,因为p_arr
不允许指向超出分配的内存。
答案 1 :(得分:1)
char (*p_arr)[1] = &arr;
创建一个指向char
指针数组的指针,指针包含一个元素((*p_arr)[1]
),并通过赋值&arr
指针获取已存在的地址包含5个元素的数组
所以printf("%c\n", p_arr[0][4]);
打印第5个元素(U),因为p_arr[0][4]
通过第1行的第5个元素
printf("%c\n", p_arr[1][4]);
会出错
所以这段代码的工作原理是2D数组像1D数组一样存储在内存中
答案 2 :(得分:1)
此声明
char (*p_arr)[1] = &arr;
不正确,因为声明的指针和初始化程序具有不兼容的类型。没有从类型char ( * )[5]
(初始值设定项的类型)到类型char ( * )[1]
的隐式转换,即已声明指针的ty [e]。因此,您需要显式转换以将一种类型的指针重新解释为另一种类型的指针,例如
char (*p_arr)[1] = ( char ( * )[1] )&arr;
至于你的问题,那么如果你有T
类型的对象,其中T
是某种类型
T obj;
和指向对象的指针,如
T *ptr = &obj;
然后表达式*ptr
或ptr[0]
产生T
类型的引用对象。
因此,我们假设您有以下声明
char arr[5] = {'A', 'E', 'I', 'O', 'U'};
char (*p_arr)[5] = &arr;
对于作为变量char[5]
类型的类型arr
,您可以引入typedef名称。
typedef char T[5];
然后声明看起来像
T arr = {'A', 'E', 'I', 'O', 'U'};
T *p_arr = &arr;
正如上面提到的,表达式*p_arr
或p_arr[0]
产生T
类型的引用对象,其类型为char[5]
。
来自C标准(6.5.3.2地址和间接操作符)
4一元*运算符表示间接。如果操作数指向a 功能,结果是功能指示符;如果它指向一个 对象,结果是指定对象的左值。如果是操作数 有类型''指向类型'',结果类型''类型''。如果 无效值已分配给指针,行为 unary *运算符未定义。
和(6.5.2.1数组下标)
2后缀表达式后跟方括号[]中的表达式是数组对象元素的下标名称。 下标operator []的定义是E1 [E2]与(*((E1)+(E2)))相同。由于适用于binary +运算符的转换规则,如果E1是数组对象(等效地,指向数组对象的初始元素的指针)并且E2是整数,则E1 [E2]指定E1的第E2个元素(从零开始计数)。
最后(6.5.6添加运算符)
7出于这些运算符的目的,指向对象的指针 不是数组的元素行为与指向的指针相同 长度为1的数组的第一个元素,对象的类型为 其元素类型。
所以在这个宣言中
char arr[5] = {'A', 'E', 'I', 'O', 'U'};
char (*p_arr)[5] = &arr;
指针p_arr
未指向数组元素。但是它可以表现为它指向长度为1的数组的第一个元素。您可以通过以下方式想象它
char arr[1][5] = { {'A', 'E', 'I', 'O', 'U'} };
char (*p_arr)[5] = arr;
因此表达式p_arr[0]
给出了想象的二维数组的第一个元素,它是char[5]
类型的元素。
答案 3 :(得分:0)
您声明p_arr是指向字符数组的指针(该数组长度为1,这是问题的确定标志)。
您可能需要更简单的语法:
char *p_arr = arr;
或者也许:
#include <stdio.h>
int main() {
char arr[] = {"Hello world"};
char *p[3] = {NULL, arr, NULL};
printf("%s %c\n", p[1], p[1][3]);
}
约翰