2014-10-29 170 views
19

我已经怀疑关于以下的代码:阵列初始化用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++但不是在c给出在第3行一个错误?

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

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

+2

你使用哪个编译器作为VS 2012将它视为错误 – 2014-10-29 10:25:44

+21

C与C++不同。 – 2014-10-29 10:26:57

+2

哪条线准确给出错误?第4行是'array2'的声明,但唯一有问题的行是'array1'的行。 – 2014-10-29 10:27:46

回答

26

这是无效的C.请参阅C11 6.7。9:

No initializer shall attempt to provide a value for an object not contained within the entity being initialized.

我猜你正在使用gcc。然后,如果你希望你的程序表现为严格的标准C,编译成这样:

gcc -std=c11 -pedantic-errors 

error: excess elements in scalar initializer

+4

这违反了约束条件,即使没有'-pedantic-errors',gcc也可以根据需要正确地发布诊断信息,而对于ISO C而言,它足够严格。实现不需要拒绝代码。 – 2014-10-29 11:12:20

+2

@BlueMoon这是因为标准中没有警告和错误等事情。对于程序员来说,错误会更好。 – Lundin 2014-10-29 11:57:10

15

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

来源:C11 draft N1570; 6.7.9 Initialisation

Constraints
2 No initializer shall attempt to provide a value for an object not contained within the entity being initialized.
3 The type of the entity to be initialized shall be an array of unknown size or a complete object type that is not a variable length array type.

绝对打破约束2.是一种int一个完整的对象类型

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

The initializer for a scalar is neither a single expression nor a single expression enclosed in braces (6.7.9).

额外:
@詹姆斯甘孜:

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. 

编制与int初始alised与initalizer列表产生一个警告(海合会):

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

但现在看来,编译器是足够聪明,只是初始化int而不是以下的内存。 demo

+2

不确定违反约束会导致未定义的行为。 C标准是陈述还是暗示? – 2014-10-29 11:19:56

+0

但是'1,2,3,4,5''可以被解释为一个初始化器。 ('int x = 1,2,3,4,5;'绝对是合法的。) – 2014-10-29 11:57:36

+2

但是'{1,2,3,4,5}!= 1,2,3,4,5'。前者是一个初始化列表,后者与逗号运算符有5个不同的值。我认为这适用于:'标量的初始化方法既不是单个表达式也不是单个表达式(6.7.9).'请纠正我错误 – Baldrickk 2014-10-29 12:00:27

2

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

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

这里的方括号实际上告诉编译器,这是一个数组,一组在您的案件数字。在这种初始化中,不需要指定数组的长度。编译器会知道。

第二种方法是定义一个数组,后初始化:

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

在这种情况下,你需要告诉编译器的阵列将是什么规模。而且,在第二种情况下,您需要手动删除内存。

+0

这不是问题的答案。 – 2014-10-29 13:07:47

11

这是因为按照C规范有效。从C11节6.7.9(初始化)

引用:

Syntax

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

那么初始化器可以是直接表达(assignment-expression以上),或初始化的大括号围列表。标准中该部分的约束不限制“正常”(非数组或非指针)变量。

这使您可以编写例如

int a = { 1 }; 
+0

这是这个答案列表中最相关的(甚至是正确的)答案。 – bitcell 2014-10-29 10:34:04

+0

我的C编译器确实接受单个值“{1}”,但是提到OP的“array1”错误C2078:太多初始值设定项“。 – 2014-10-29 10:38:46

+0

C继续给我留下了深刻的印象 – 2014-10-29 10:42:48

1

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

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

编辑:

我应该写的蠢事之前根据不同的编译器都进行了测试。

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

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

+0

编译器如何知道它是一个'char'数组?为什么不是'整数'? '是任何人的双重身份?对不起,你的回答是无稽之谈。初始化器列表在'C'中没有类型。 – GreenScape 2014-10-29 13:00:24

+1

@GreenScape:你是对的!我已经更新了我的答案... – 2014-10-29 13:30:05

+0

你可以做一些令人讨厌的reinterpret转换来使指针成为'int',尽管我怀疑不是初始化。+1进行虚假陈述,然后从中学习。 – imallett 2014-10-29 18:12:17

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++标准,它明确地说,

If T is a scalar type, then a declaration of the form

 
    T x = { a }; 

is equivalent to

 
    T x = a; 

哪个不留下太多的蠕动室:在C++中,声明似乎明确的法律;只有在C有些模棱两可的地方。

+5

我不认为这里存在歧义,语法根本不允许'''成为逗号运算符。如果我们看一下'6.7.8'为initialzer语法包括'分配,expression'不能让我们到一个逗号操作符不'()'...所以我们可以做'{(1,2,3,4 ,5)}'但这有可疑的用处。 – 2014-10-29 12:04:12

+0

@ShafikYaghmour这是一个很好的观点。但是这似乎意味着'int a = 1,2,3;'也是非法的。不过,我确信我已经使用了它(或类似的东西)。或者,也许我总是把它放在括号内;我不确定。 (我使用括号来讲清楚只有一个表达所涉及的读卡器。) – 2014-10-29 12:12:31

+0

'的GCC -std = C99 = -pedantic拒绝errors'编译'INT A = 1,2;'。您的建议的标准的读出也将导致有问题的,例如,'INT A = 1,B = 2;'在块范围时B'的'文件范围声明是可见的或用语句表达式的GCC扩展(GCC扩展旨在不与ISO C冲突)。 – mafso 2014-10-29 17:15:36

2

正如你的编译器所说,这对于C来说也是不正确的。这里需要注意的是,如果出现这种“约束违规”(官方术语),编译器可能会产生一个诊断(您的编译器会这样做)并继续。

这就是为什么一般你应该确保你的代码编译没有任何诊断任何。