关于int * a = {1,2,3}的有效性。为什么随后的*崩溃?

时间:2018-02-01 16:27:26

标签: c segmentation-fault

int main()
{
   int *a={1,2,3}; //which value is stored and where it is stored 
   printf("\n%d",*a); //crashes here
}

请解释上述原因导致崩溃的原因。

3 个答案:

答案 0 :(得分:5)

发布的代码具有未定义的行为,因此可以编译和执行,但结果是不可预测的。一种可能的结果是分段错误。

该行:

int *a={1,2,3};

尝试使用初始化列表(包含太多元素;这应该生成警告)初始化指向int的指针,但此初始化列表一个数组。

一种解决方案是使用实际数组:

int arr[] = { 1, 2, 3 };
int *a = arr;

这里arr[]是一个不完整的数组类型。初始化列表用于初始化数组arr[],当达到初始化列表的末尾时,数组类型完成。现在a是指向数组arr[]的第一个元素的指针,其类型为int [3]

自C99起可用的另一个选项是使用复合文字

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

这里,复合文字创建一个匿名数组,a指向该数组的第一个元素。请注意,对于发布的代码,此匿名数组将具有自动存储持续时间,也就是说,仅当程序执行在main()块内时,它才存在。一般来说,根据§6.5.2.5 5 of the C11 Draft Standard

  

如果复合文字出现在函数体外,则该对象具有静态存储持续时间;否则,它具有与封闭块相关的自动存储持续时间。

答案 1 :(得分:4)

首先来自标准

int *a={1,2,3}

所以你正在使用初始化列表。

来自标准6.7.9p11

  

标量的初始值设定项应为单个表达式,可选择用大括号括起来。对象的初始值是表达式的初始值(转换后);与简单赋值相同的类型约束和转换适用,将标量的类型作为其声明类型的非限定版本。

就是这样。 int *a = {1}; 不是合法代码。

但即使你尝试这样的事情

error: invalid conversion from 'int' to 'int*' [-fpermissive]

编译器会评论int *a = {(int*)1};

你可以做到这一点,(但你可以做的不多)

{{1}}

但取消引用这可能会导致未定义的行为。 (即分段错误)。

答案 2 :(得分:2)

int *a={1,2,3};此处a是一个指针,它期待一些有效地址,程序员的工作是分配一些有效地址这样它就无法指向随机地址。

虽然它是未定义的行为,但此处a是使用第一个元素初始化的。所以看起来像

 int *a = 1;

当您执行*a时,它会因为您尝试取消引用无效地址而崩溃。

解决方案首先动态分配内存,然后按

进行操作
int *a = malloc( 3 * sizeof(int));
        a[0]= 1;
        a[1]= 2;
        a[2]= 3;

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

完成作业后,释放内存以避免内存泄漏

free(a);

注意:初始化列表{ }与字符串文字" "不同。

int *a = {1}; /* a didn't get any address */
int *a = "1"; /* a gets address*/