简体   繁体   English

初始化char-array和char与整数文字的区别

[英]Difference in initializing char-array and char with integer literals

On my system ( 4.13.11-1-ARCH, gcc 7.2.0 ) char is signed . 在我的系统( 4.13.11-1-ARCH,gcc 7.2.0 )上signed char When initializing an array of char with an integer literal like this: 初始化带有integer literalchar数组时,如下所示:

const char mydata[] = {
    0x80
};

I get the following error: 我收到以下错误:

error: narrowing conversion of ‘128’ from ‘int’ to ‘char’ inside { } [-Wnarrowing]

However, when I instead do const char data = 0x80 the compiler is not worried of any narrowing, although it happens of course. 但是,当我改为执行const char data = 0x80 ,编译器并不担心任何缩小,尽管它当然会发生。 The output is 7F , the highest positive signed char value. 输出为7F ,最高正有signed char值。

Question

Why is the compiler not equally worried about truncation in both cases? 为什么编译器在两种情况下都不会同样担心截断?

This is actually one of the reasons why {} initialization should be prefered: It does not allow narrowing conversions. 这实际上是应该首选{}初始化的原因之一:它不允许缩小转换。 In contrast to this, the old way of initalization (as in const char data = 0x80 ) does allow narrowing conversions. 与此相反,旧的初始化方式(如const char data = 0x80 )确实允许缩小转换。

An initializer of the form const char c = 0x80 is a much older construct than initializer lists, which have been introduced later. 形式为const char c = 0x80初始化程序是比初始化程序列表更旧的构造,后面已经介绍过。 So it was possible to define stricter rules for initializer lists, while these rules where not applied to "older" initializers (probably because of not to break "older" code more than necessary). 因此可以为初始化程序列表定义更严格的规则,而这些规则不适用于“较旧”的初始化程序(可能是因为不会超出必要的“旧”代码)。

Hence, initializer lists as defined in this online c++ standard draft forbid such narrowing: 因此, 此在线c ++标准草案中定义的初始化列表禁止此类缩小:

8.5.1 Aggregates 8.5.1聚合

(2) When an aggregate is initialized by an initializer list, as specified in [dcl.init.list], the elements of the initializer list are taken as initializers for the members of the aggregate, in increasing subscript or member order. (2)当聚合由初始化列表初始化时,如[dcl.init.list]中所指定的,初始化列表的元素被视为聚合成员的初始化者,增加下标或成员顺序。 Each member is copy-initialized from the corresponding initializer-clause. 每个成员都是从相应的initializer子句复制初始化的。 If the initializer-clause is an expression and a narrowing conversion ([dcl.init.list]) is required to convert the expression, the program is ill-formed. 如果initializer子句是一个表达式,并且转换表达式需要缩小转换([dcl.init.list]),则程序格式错误。 ... ...

BTW: If you use a brace initializer like const char data { 0x80 } , you will get an error, too. 顺便说一句:如果你使用像const char data { 0x80 }这样的大括号初始化器,你也会得到一个错误。 So the stricter rules are due to brace-initializers / initializer lists, and not due to whether you initialize an array or a scalar value. 因此更严格的规则是由于括号初始化器/初始化器列表,而不是由于您是初始化数组还是标量值。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM