使用数组初始化指针时会发生什么?

时间:2018-02-22 10:40:11

标签: c arrays pointers

我理解在某种情况下数组如何衰变成指向第一个元素的指针。

我知道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),并分别返回159

我尝试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搜索,无法真正找到我要找的东西。

4 个答案:

答案 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)的倍数完成的指针算法产生59

答案 1 :(得分:4)

ptr+1基本上是指针算术,在您的情况下sizeof(int)似乎是4。这就是为什么结果分别是1+41+2*4

指针算术由它指向的对象决定,int在这里。指针按sizeof(int)移动,这就是原因。

另外注意另一件事,你使用了大括号封闭的初始化程序,它为{}内的多个参数生成了警告。在这种情况下,ptr1初始化。这样做的行为没有定义,但在你的情况下,似乎是在列表中取第一个值。

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#6.7.9p11

  

标量的初始值设定项应为单个表达式,可选择用大括号括起来。 ..

为标量赋予多个初始化程序是未定义的行为 来自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};