C中的数组初始化
我对以下代码有疑问:
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
实际上是一个int
而array2
和array3
是数组,所以为什么c
编译器没有显示错误,只是一个警告:“标量初始化中的多余元素”
是否使用了这样的定义,为什么它在c
有效?
它无效C.见C11 6.7.9:
初始化程序不应尝试为未初始化的实体中包含的对象提供值。
我猜你正在使用gcc。 然后,如果您希望程序的行为与严格的标准C一样,请按以下方式编译:
gcc -std=c11 -pedantic-errors
给
错误:标量初始化程序中的多余元素
它在C中无效。它对代码的检查较少。 这是未定义的行为。
来自: C11草案N1570; 6.7.9初始化
约束
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而不是以下内存。 演示
它符合C规范。
引自C11第6.7.9节(初始化):
句法
1 initializer: assignment-expression { initializer-list } { initializer-list , }
因此,初始化程序可以是直接表达式(上面的assignment-expression
),也可以是括号括起来的初始化程序列表。 标准的该部分中的约束不限制“正常”(非数组或非指针)变量。
这允许你写例如
int a = { 1 };
和其他人一样,我认为你想知道的是:
int array1 = {1,2,3,4,5};
在这种情况下,C和C ++之间没有区别; 这条线在两种语言中都是合法的,但它并不代表你的想法。 在C和C ++中,都有一个声明,如果类型是标量类型( int
is),那么{...}
的内容必须是单个表达式。 并且1,2,3,4,5
可以解释为单个表达式(使用逗号运算符); 就像是:
int array1 = 1, 2, 3, 4, 5;
显然是合法的。
然而,它有些含糊不清,因为在这两种语言中,这种初始化的语法都是标点符号,而不是操作符。 所以这是一个解释问题; 是内容必须是单个表达式语法的约束(这将导致逗号成为运算符)或对评估指定语法的结果的约束的声明。 我的直觉是第二个是意图,声明应该导致错误。 但差异不在C和C ++之间,而是在编译器的作者解释标准的方式之间。
编辑:
重新阅读更接近:在C ++标准中,它明确地说明了这一点
如果T是标量类型,则表示声明
T x = {a};相当于
T x = a;
这并没有留下太多的蠕动空间:在C ++中,声明似乎显然是合法的; 它只存在于C中,有些含糊不清。
在C / C ++中初始化数组的正确方法是:
int array2[] = {1,2,3,4,5};
这里的方括号实际上告诉编译器这是一个数组,在你的情况下是一组数字。 以这种初始化方式,不必指定数组的长度。 编译器会知道。
第二种方法是定义一个数组并对其进行初始化:
int array3[5]; int *array = new int[5];
在这种情况下,您需要通知编译器数组的大小。 此外,在第二种情况下,您需要手动删除内存。
正如您的编译器所说,这对C来说也是不正确的。 这里需要注意的重要一点是,在这种“约束违规”(官方术语)的情况下,编译器可能只生成一个诊断(编译器所做的)并继续。
这就是为什么通常你应该确保你的代码编译而没有任何诊断。
C是一种低级许可语言。 它允许影响指向int的指针。
int array1 = {1,2,3,4,5};
编辑:
我应该在编写愚蠢的东西之前在不同的编译器下测试它。
这被MSVC(2008)拒绝为错误。
gcc和clang都会excess elements in scalar initializer
发出警告excess elements in scalar initializer
,只会影响1到a
。