C中的数组初始化

时间:2014-10-29 10:23:51

标签: c++ c arrays

我怀疑以下代码:

int main()
{
    int array1 = {1,2,3,4,5}; //error in c++ , warning in c
    int array2[] = {1,2,3,4,5};
    int array3[5] = {1,2,3,4,5};
}

这段代码在c++中的第3行但在c中没有出现错误?

我知道array1实际上是intarray2array3是数组,所以为什么没有c编译器显示错误,但只是一个警告:"标量初始化中的多余元素"

是否使用了这样的定义,为什么它在c中有效?

7 个答案:

答案 0 :(得分:26)

无效C.见C11 6.7.9:

  

初始化程序不应尝试为对象提供值   包含在正在初始化的实体中。

我猜你正在使用gcc。然后,如果您希望程序的行为与严格的标准C一样,请按以下方式编译:

gcc -std=c11 -pedantic-errors

给出

  

错误:标量初始值设定项中的多余元素

答案 1 :(得分:15)

在C中没有。它对代码的检查较少。这是未定义的行为。

来自:C11 draft N1570; 6.7.9 Initialisation

  

约束
  2初始化程序不应试图为未初始化的实体中未包含的对象提供值   3要初始化的实体的类型应为未知大小的数组或不是可变长度数组类型的完整对象类型。

绝对违反约束2. int 完整对象类型是吗?

附件J.2(未定义的行为):

  

标量的初始值设定项既不是单个表达式,也不是括在大括号中的单个表达式(6.7.9)。

额外:
@James Kanze:

prog.c:4:12: error: expected identifier or ‘(’ before numeric constant
  int i = 1,2,3,4,5;
            ^

你可以做到,但你需要做一个表达式:

int i = (1,2,3,4,5); //need parenthesis, evaluates to 5, values 1-4 thrown away.

使用 initalizer-list 初始化的int进行编译会产生警告(在gcc中):

prog.c:5:2: warning: excess elements in scalar initializer [enabled by default]
  int j = {1,2,3,4,5};
  ^

但似乎编译器足够聪明,只能初始化int而不是以下内存。 demo

答案 2 :(得分:11)

根据C规范有效。

引自C11第6.7.9节(初始化):

  

语法

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

因此初始化程序可以是直接表达式(上面的assignment-expression),也可以是括号括起来的初始化程序列表。标准的该部分中的约束并不限制这对于#34;正常" (非数组或非指针)变量。

这允许你写例如。

int a = { 1 };

答案 3 :(得分:3)

和其他人一样,我认为你想知道的是:

int array1 = {1,2,3,4,5};

在这种情况下,C和C ++之间没有区别;这条线在两种语言中都是合法的,但它并不代表你的想法。在C和C ++中,都有一个声明,如果类型是标量类型(int是),那么{...}的内容必须是单个表达式。并且1,2,3,4,5可以解释为单个表达式(使用逗号运算符);类似的东西:

int array1 = 1, 2, 3, 4, 5;

显然是合法的。

但是,它有些含糊不清,因为在这两种语言中,这种初始化的语法会产生,标点符号,而不是运算符。所以这是一个解释问题;是内容必须是单个表达式语法约束的语句(这将导致逗号成为运算符),或对评估指定语法的结果的约束。我的直觉是第二个是意图,声明应该导致错误。但C和C ++之间的区别并不在于编译器的作者解释标准的方式。

编辑:

重新阅读更接近:在C ++标准中,它明确地说明了

  

如果T是标量类型,则表示形式为

的声明
    T x = { a };
     

相当于

    T x = a;

这并没有留下太多的蠕动空间:在C ++中,声明显然是合法的;它只存在于存在歧义的C中。

答案 4 :(得分:2)

在C / C ++中初始化数组的正确方法是:

int array2[] = {1,2,3,4,5};

这里的方括号实际上告诉编译器这是一个数组,在你的情况下是一组数字。以这种初始化方式,不必指定数组的长度。编译器会知道。

第二种方法是定义一个数组并对其进行初始化:

int array3[5];
int *array = new int[5];

在这种情况下,您需要通知编译器数组的大小。此外,在第二种情况下,您需要手动删除内存。

答案 5 :(得分:2)

正如您的编译器所说,这对C来说也不正确。这里需要注意的重要一点是,在出现“约束违规”(官方术语)的情况下,编译器可能只生成一个诊断(编译器所做的)并继续。

这就是为什么你应该确保你的代码在没有任何诊断的情况下进行编译。

答案 6 :(得分:1)

C是一种低级许可语言。 它允许影响指向int的指针。

int array1 = {1,2,3,4,5};

编辑:

我应该在编写愚蠢的东西之前在不同的编译器下测试它。

这被MSVC(2008)拒绝为错误。

gcc和clang都会发出警告excess elements in scalar initializer,只会影响1到a