int main()
{
int *a={1,2,3}; //which value is stored and where it is stored
printf("\n%d",*a); //crashes here
}
请解释上述原因导致崩溃的原因。
答案 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*/