Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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. 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.

Question

Why is the compiler not equally worried about truncation in both cases?

like image 547
Marcus Avatar asked Nov 15 '17 19:11

Marcus


People also ask

What is difference between char array and int array?

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.

What is the correct way to initialize character array?

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.

What is the difference between char * and char []?

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.

What is a char * array in C?

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)


2 Answers

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.

like image 81
463035818_is_not_a_number Avatar answered Oct 09 '22 03:10

463035818_is_not_a_number


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.

like image 33
Stephan Lechner Avatar answered Oct 09 '22 04:10

Stephan Lechner