web-dev-qa-db-fra.com

Avertissements constants à plusieurs caractères

Pourquoi est-ce un avertissement? Je pense qu'il y a de nombreux cas où il est plus clair d'utiliser des constantes multi-char int au lieu de nombres "sans signification" ou au lieu de définir des variables const avec la même valeur. Lors de l'analyse syntaxique des types de fichiers wave/tiff/autres, il est plus clair de comparer les valeurs lues avec certains "EVAW", "données", etc. au lieu de leurs valeurs correspondantes.

Exemple de code:

int waveHeader = 'EVAW';

Pourquoi cela donne-t-il un avertissement?

33
Felics

Selon la norme (§6.4.4.4/10)

La valeur d'une constante de caractère entier contenant plus d'un caractère (par exemple, 'ab'), [...] est définie par l'implémentation.

long x = '\xde\xad\xbe\xef'; // yes, single quotes

Ceci est valide ISO 9899: 2011 C. Il se compile sans avertissement sous gcc avec -Wall, et un avertissement de "constante de caractères multi-caractères" avec -pedantic.

De Wikipedia :

Les constantes à plusieurs caractères (par exemple 'xy') sont valides, bien que rarement utiles - elles permettent de stocker plusieurs caractères dans un entier (par exemple 4 ASCII peuvent tenir dans un entier 32 bits, 8 dans un 64 bits). Étant donné que l'ordre dans lequel les caractères sont regroupés dans un entier n'est pas spécifié, l'utilisation portable de constantes à plusieurs caractères est difficile.

Pour des raisons de portabilité, n'utilisez pas de constantes à plusieurs caractères avec des types intégraux.

36
user195488

Cet avertissement est utile pour les programmeurs qui écriraient par erreur 'test' où ils auraient dû écrire "test".

Cela se produit beaucoup plus souvent que les programmeurs qui souhaitent réellement des constantes multi-caractères.

14
Didier Trosset

Si vous êtes heureux de savoir ce que vous faites et pouvez accepter les problèmes de portabilité, sur GCC par exemple, vous pouvez désactiver l'avertissement sur la ligne de commande:

-Wno-multichar

J'utilise cela pour mes propres applications pour travailler avec les en-têtes de fichiers AVI et MP4 pour des raisons similaires à vous.

13
blueshift

Même si vous êtes prêt à rechercher le comportement défini par votre implémentation, les constantes multi-caractères varieront en fonction de l'endianité.

Mieux vaut utiliser une structure (POD) {char [4]}; ... puis utilisez un UDL comme "WAVE" _4cc pour construire facilement des instances de cette classe

4
o11c

La solution la plus simple compatible C/C++ avec tout compilateur/standard a été mentionnée par @leftaroundabout dans les commentaires ci-dessus:

int x = *(int*)"abcd";

Ou un peu plus précis:

int x = *(int32_t*)"abcd";

Une autre solution, également compatible avec tout compilateur/standard C/C++ (sauf clang ++, qui a un bug conn ):

int x = ((union {char s[5]; int number;}){"abcd"}).number;

/* just a demo check: */
printf("x=%d stored %s byte first\n", x, x==0x61626364 ? "MSB":"LSB");

Ici, le littéral de chaîne "abcd" est converti en tableau, puis l'union anonyme est utilisée pour donner un nom de symbole Nice au résultat numérique souhaité.

2
sqr163