C语言 关于 int *a={1,2,3} 的有效性.为什么后续的*a崩溃?


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

请解释为什么上述内容崩溃。

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

该行:

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()块内时才存在。一般而言,根据C11标准草案§6.5.2.5 5

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

首先来自标准

initializer:
assignment-expression
{ initializer-list }
{ initializer-list , }

所以你正在使用初始值设定项列表。

从标准 6.7.9p11

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

就是这样。int *a={1,2,3}不是法典。

但即使你尝试这样的事情

int *a = {1};

编译器将大约error: invalid conversion from 'int' to 'int*' [-fpermissive].

不过你可以这样做,(但你对此无能为力)

int *a = {(int*)1};

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

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*/

相关内容

  • 没有找到相关文章

最新更新