"为int * NUMS = {5,2,1,4}"导致分段故障 [英] "int *nums = {5, 2, 1, 4}" causes a segmentation fault

查看:289
本文介绍了"为int * NUMS = {5,2,1,4}"导致分段故障的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

int *nums = {5, 2, 1, 4};
printf("%d\n", nums[0]);

导致段错误,而

int nums[] = {5, 2, 1, 4};
printf("%d\n", nums[0]);

没有。
现在:

doesn't. Now:

int *nums = {5, 2, 1, 4};
printf("%d\n", nums);

印刷5。

在此基础上,我推测,数组初始化符号,{},一味并将数据导入任何变量是在左边。当它为int [],根据需要的阵列被充满。当它为int *,指针是由5填满,并且指针存储在哪里后存储器位置被2,1填满,和4。所以NUMS [0]尝试DEREF 5,使段错误。

Based on this, I have conjectured that the array initialization notation, {}, blindly loads this data into whatever variable is on the left. When it is int[], the array is filled up as desired. When it is int*, the pointer is filled up by 5, and the memory locations after where the pointer is stored are filled up by 2, 1, and 4. So nums[0] attempts to deref 5, causing a segfault.

如果我错了,请大家指正。如果我是正确的,请详细说明,因为我不明白为什么初始化数组的工作他们做的方式。

If I'm wrong, please correct me. And if I'm correct, please elaborate, because I don't understand why array initializers work the way they do.

推荐答案

有是在C(愚蠢)规则说,任何普通变量可以用大括号内的初始化列表初始化,就好像它是一个数组。

There is a (stupid) rule in C saying that any plain variable may be initialized with a brace-enclosed initializer list, just as if it was an array.

例如,你可以写 INT X = {0}; ,这是完全等同于 INT X = 0;

For example you can write int x = {0};, which is completely equivalent to int x = 0;.

所以,当你写为int * NUMS = {5,2,1,4}; 你实际上是给人一种初始化列表到一个指针变量。然而,这仅仅是一个单一的变量,因此它只会被分配的第一个值5,列表的其余部分被忽略(实际上我不认为code过量初始化甚至应该有一个严格的编译器编译) - 它不会写入到内存的。在code等同于为int * NUMS = 5; 。这意味着, NUMS 应该在点的地址 5

So when you write int *nums = {5, 2, 1, 4}; you are actually giving an initializer list to a single pointer variable. However, it is just one single variable so it will only get assigned the first value 5, the rest of the list is ignored (actually I don't think that code with excess initializers should even compile with a strict compiler) - it does not get written to memory at all. The code is equivalent to int *nums = 5;. Which means, numsshould point at address 5.

在这一点上,你应该已经得到了2编译器警告/错误:

At this point you should already have gotten two compiler warnings/errors:


  • 分配整数,未强制转换为指针。

  • 在初始化列表中多余的元素。

和那当然code将崩溃,因为 5 燃烧是最有可能不是你被允许提领与的有效地址NUMS [0]

And then of course the code will crash and burn since 5 is most likely not a valid address you are allowed to dereference with nums[0].

作为一个方面说明,你应该的printf %P 符或指针的地址,否则要调用未定义行为。

As a side note, you should printf pointer addresses with the %p specifier or otherwise you are invoking undefined behavior.

我不太清楚你正在尝试做的,但如果你想设置一个指针指向数组点,你应该做的:

I'm not quite sure what you are trying to do here, but if you want to set a pointer to point at an array, you should do:

int nums[] = {5, 2, 1, 4};
int* ptr = nums;

// or equivalent:
int* ptr = (int[]){5, 2, 1, 4};

或者,如果你想创建一个指针数组:

Or if you want to create an array of pointers:

int* ptr[] = { /* whatever makes sense here */ };


修改

经过一番研究,我可以说,多余的元素初始化列表的确不是有效的C - 这是一个的 GCC扩展

After some research I can say that the "excess elements initializer list" is indeed not valid C - it is a GCC extension.

标准 6.7.9初始化说(重点煤矿):

2 否初始化应尝试为对象的值不
  其中所包含的实体,被初始化。

/ - /

11 的初始化为一个标量应该是单个前pression,
  可选大括号括起来。
对象的初始值是
  恩pression的(转换后);相同类型的约束和
  转换为简单赋值申请,采取的类型
  标是其声明的类型的无保留意见的版本。

11 The initializer for a scalar shall be a single expression, optionally enclosed in braces. The initial value of the object is that of the expression (after conversion); the same type constraints and conversions as for simple assignment apply, taking the type of the scalar to be the unqualified version of its declared type.

标量型是一个标准的术语,指单一变量,这些变量数组,结构或联合类型的不(那些被称为聚合型)。

"Scalar type" is a standard term referring to single variables that are not of array, struct or union type (those are called "aggregate type").

所以,用简单的英语标准说:当你初始化一个变量,随意绕前初始化pression一些额外的括号折腾,只是因为你可以

So in plain English the standard says: "when you initialize a variable, feel free to toss in some extra braces around the initializer expression, just because you can."

这篇关于"为int * NUMS = {5,2,1,4}"导致分段故障的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
相关文章
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆