Многосимвольные постоянные предупреждения
Почему это предупреждение? Я думаю, что есть много случаев, когда более понятно использовать константы 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