我理解在某种情况下数组如何衰变成指向第一个元素的指针。
我知道int array[] = {1,2,3,4,5}
创建了一个数组,我们可以创建一个指针int *ptr = array
,在指定之后,它也指向数组的第一个元素。
问题是,当我这样做时会发生什么:int *ptr = {1,2,3,4,5}
?
我尝试了printf("%d",ptr)
,printf("%d",ptr+1)
和printf("%d",ptr+2)
,并分别返回1
,5
和9
。
我尝试printf("%d",*ptr)
并返回segmentation fault
所以我看到ptr
指向数组{1,2,3,4,5}
,并再次尝试:
for(int i=0;i<5;i++){
printf("%d",(*p)[i]);
}
然后返回subscripted value is neither array nor pointer nor vector
然后我用Google搜索,无法真正找到我要找的东西。
答案 0 :(得分:6)
使用decent compilation flags立即给出答案:
main.cpp:1:13: error: incompatible integer to pointer conversion initializing 'int *' with an expression of type 'int' [-Werror,-Wint-conversion] int *ptr = {1,2,3,4,5}; ^ main.cpp:1:15: error: excess elements in scalar initializer [-Werror] int *ptr = {1,2,3,4,5}; ^
您隐式将1
转换为int *
,并丢弃多余的初始化程序。
以sizeof(int)
(此处为4)的倍数完成的指针算法产生5
和9
。
答案 1 :(得分:4)
是ptr+1
基本上是指针算术,在您的情况下sizeof(int)
似乎是4
。这就是为什么结果分别是1+4
和1+2*4
。
指针算术由它指向的对象决定,int
在这里。指针按sizeof(int)
移动,这就是原因。
另外注意另一件事,你使用了大括号封闭的初始化程序,它为{}
内的多个参数生成了警告。在这种情况下,ptr
由1
初始化。这样做的行为没有定义,但在你的情况下,似乎是在列表中取第一个值。
printf("%d",*ptr)
正试图读取ptr
指向的地址中的内容。在您的情况下,这会产生分段错误 - 这意味着您尝试读取您未经许可或无法访问的内存。
为了让你朝着正确的方向前进,你可以这样做: -
int a[5]={1,2,3,4,5};
int *ap = a;
for(size_t i = 0; i < sizeof(a)/sizeof(a[0]); i++)
// work with ap[i].
int (*p)[5] = &a;
for(size_t i = 0; i < sizeof(a)/sizeof(a[0]); i++)
// work with (*p)[i]
答案 2 :(得分:4)
本声明
int *ptr = {1,2,3,4,5};
有undefined behavior。未定义的行为包括它可能执行不正确(崩溃或静默生成不正确的结果),或者它可能偶然地完成程序员的预期。
编译具有此语句的程序 - int *ptr = {1,2,3,4,5}
时,编译器必须发出警告消息 -
warning: excess elements in scalar initializer
int *ptr = {1,2,3,4,5};
^
算术类型和指针类型统称为标量类型。
标量的初始值设定项应为单个表达式,可选择用大括号括起来。 ..
为标量赋予多个初始化程序是未定义的行为 来自C Standards#J.2 Undefined behavior:
标量的初始值设定项既不是单个表达式,也不是括在大括号中的单个表达式
答案 3 :(得分:3)
定义
int *ptr = {1,2,3,4,5};
相当于
int *ptr = 1;
其余的初始化程序无效,绝大多数都不能使它成为一个数组。
如果你想要一个指向数组的指针而不实际定义一个数组,你可以使用compound literals:
int *ptr = (int[]){1, 2, 3, 4, 5};