On my system (4.13.11-1-ARCH, gcc 7.2.0) char
is signed
. When initializing an array of char
with an integer literal
like this:
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. The output is 7F
, the highest positive signed char
value.
Why is the compiler not equally worried about truncation in both cases?
A character array contains characters; an integer array contains integers. And assuming you know the difference between a character and an integer, that's all the explanation you need… that's about it.
An array of character type may be initialized by a character string literal or UTF−8 string literal, optionally enclosed in braces. Successive bytes of the string literal (including the terminating null character if there is room or if the array is of unknown size) initialize the elements of the array.
Difference between char s[] and char *s in C There are some differences. The s[] is an array, but *s is a pointer. For an example, if two declarations are like char s[20], and char *s respectively, then by using sizeof() we will get 20, and 4. The first one will be 20 as it is showing that there are 20 bytes of data.
In C, an array of type char is used to represent a character string, the end of which is marked by a byte set to 0 (also known as a NUL character)
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.
An initializer of the form const char c = 0x80
is a much older construct than
initializer lists, which have been introduced later. 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:
8.5.1 Aggregates
(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. Each member is copy-initialized from the corresponding initializer-clause. 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. ...
BTW: If you use a brace initializer like const char data { 0x80 }
, you will get an error, too. So the stricter rules are due to brace-initializers / initializer lists, and not due to whether you initialize an array or a scalar value.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With