web-dev-qa-db-fra.com

"Rétrécissement de la conversion de" int "en" char "à l'intérieur de {}" pour les valeurs légales lors de la compilation croisée

J'ai un projet C++ que je compile à la fois en utilisant g++ sur ma machine (compilation en "Host") et sur un processeur ARM utilisant un compilateur croisé (dans mon cas arm-cortex_a8-linux-gnueabi-g++). Je suis en train de convertir en C++ 0x/11 standart et il y a une erreur que je reçois lors de la compilation de la liste d'initialisation, que j'ai pu reproduire dans l'extrait de code suivant:

int main(void) {
    char c[1] = {-108};
}

Ce programme semble correct comme -108 est une valeur légale pour un char. Compiler ceci avec g++ ne génère aucune erreur avec la ligne de commande suivante:

g++ example.cc -std=c++0x

Cependant, lorsque je compile avec le compilateur croisé, comme ceci:

arm-cortex_a8-linux-gnueabi-g++ example.cc -std=c++0x

J'obtiens l'erreur suivante:

example.cc: In function 'int main()':
example.cc:2:22: error: narrowing conversion of '-0x0000000000000006c' from 'int' to 'char' inside { } [-fpermissive]

Étant donné que la valeur est légale, cela semble être un bug. Pouvez-vous expliquer pourquoi j'obtiens cette erreur et que faire pour la résoudre?

Modifier : notez que l'utilisation de valeurs positives (par exemple, 108) est légal et n'entraîne pas d'erreur sur les deux compilateurs.

13
Andy Thomas

Lorsque vous déclarez une variable en tant que char, elle dépend de l'implémentation, qu'elle soit signée ou non signée. Si vous devez pouvoir stocker des valeurs négatives, vous devez le déclarer signed explicitement, plutôt que de vous fier à la valeur par défaut définie par l'implémentation.

signed char c[1] = { -108 };
20
Barmar

Puisque la valeur est légale

Comment sais-tu ça? chars la signature est définie par l'implémentation. Et s'il n'est pas signé, votre code est mal formé par le rétrécissement - §8.5.4/7:

Une conversion rétrécissante est une conversion implicite
[…]
(7.4) - d'un type entier […] à un type entier qui ne peut pas représenter toutes les valeurs du type original, sauf lorsque la source est une expression constante dont la valeur après l'intégrale les promotions s'inscriront dans le type cible.

§8.5.1/2:

Si la clause d'initialisation est une expression et qu'une conversion de rétrécissement (8.5.4) est requise pour convertir l'expression, le programme est mal formé.

Cependant, si vous avez besoin d'un char signé, utilisez signed char.

signed char c[1] = {-108};

… Est garanti de fonctionner.

9
Columbo