Многосимвольные постоянные предупреждения

Почему это предупреждение? Я думаю, что есть много случаев, когда более понятно использовать константы multi-char int вместо чисел "без смысла" или вместо определения константных переменных с одинаковым значением. При синтаксическом анализе файлов типа wave/tiff/ другие более понятно сравнивать прочитанные значения с некоторыми "EVAW", "data" и т. Д. Вместо их соответствующих значений.

Образец кода:

int waveHeader = 'EVAW';

Почему это дает предупреждение?

4 ответа

Решение

Согласно стандарту (§6.4.4.4/10)

Значение целочисленной символьной константы, содержащей более одного символа (например, 'ab'), [...] определяется реализацией.

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

Это действительно ISO 9899:2011 C. Он компилируется без предупреждения под gcc с -Wallи предупреждение "многосимвольная символьная константа" с -pedantic,

Из Википедии:

Многосимвольные константы (например, "xy") допустимы, но редко бывают полезными - они позволяют хранить несколько символов в целых числах (например, 4 символа ASCII могут помещаться в 32-разрядное целое число, 8 в 64-разрядное). Поскольку порядок, в котором символы упакованы в одно целое, не указан, использование многосимвольных констант переносимо.

Ради переносимости не используйте многосимвольные константы с целочисленными типами.

Это предупреждение полезно для программистов, которые по ошибке написали бы 'test' где они должны были написать "test",

Это случается гораздо чаще, чем программисты, которым действительно нужны константы multi-char int.

Если вы счастливы, что знаете, что делаете, и можете принять проблемы с переносимостью, например, в GCC вы можете отключить предупреждение в командной строке:

-Wno-multichar

Я использую это для своих собственных приложений для работы с заголовками файлов AVI и MP4 по тем же причинам, что и вы.

Даже если вы захотите посмотреть, какое поведение определяет ваша реализация, многосимвольные константы все равно будут различаться в зависимости от порядка байтов.

Лучше использовать (POD) struct { char[4] }; ... а затем использовать UDL, такой как "WAVE"_4cc, чтобы легко создавать экземпляры этого класса

Простейшее C/C++ любое компилятор / стандартное совместимое решение, было упомянуто @leftaroundabout в комментариях выше:

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

Или немного конкретнее:

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

Еще одно решение, также совместимое с любым компилятором / стандартом C/C++ (кроме clang++, в котором есть известная ошибка):

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");

Здесь строковый литерал "abcd" преобразуется в массив, а затем используется анонимное объединение, чтобы дать хорошее имя-символ желаемому числовому результату.

Если вы хотите отключить это предупреждение, важно знать, что в GCC и Clang есть два связанных параметра предупреждения: параметры компилятора GCC -wno-four-char-constants и -wno-multichar

Другие вопросы по тегам