多字符恒定警告

Mir*_*pas 35 c c++ portability casting compiler-warnings

为什么这是一个警告?我认为在很多情况下使用multi-char int常量而不是"无意义"数字或者使用相同值定义const变量更为明确.解析wave/tiff /其他文件类型时,可以更清楚地将读取值与某些"EVAW","数据"等进行比较,而不是相应的值.

示例代码:

int waveHeader = 'EVAW';
Run Code Online (Sandbox Code Playgroud)

为什么这会发出警告?

小智 38

根据标准(§6.4.4.4/ 10)

包含多个字符的整数字符常量的值(例如,'ab'),[...]是实现定义的.

long x = '\xde\xad\xbe\xef'; // yes, single quotes
Run Code Online (Sandbox Code Playgroud)

这是有效的ISO 9899:2011 C.它编译没有警告下gcc-Wall,和"多字符常量"与警告-pedantic.

来自维基百科:

多字符常量(例如'xy')是有效的,虽然很少有用 - 它们允许一个整数存储多个字符(例如,4个ASCII字符可以容纳32位整数,8个容纳在64位整数中).由于未指定将字符打包到一个int中的顺序,因此难以手动使用多字符常量.

为了便于携带,请不要使用带有整数类型的多字符常量.

  • 我不确定最后一句是什么意思; 多字符常量总是具有整数类型(并且这种没有前缀的常量总是具有类型`int`). (4认同)
  • 基本上是说,您无法可移植地将打包字符的 int 字节顺序解密为 Little-Endian 或 Big-Endian,因此为了可移植性,不要使用 char 以外的数据类型来存储字符。在 x86 中,整数以 Little-Endian 格式保存,字节或 8 位字符保存为单个字节,技术上没有字节顺序,如果我们将内容标记为单个数据类型,则为字符串,字符串,基本上保存为 Big-Endian 字符串。那么multichar-char是Big-Endian还是Little-Endian?我们需要将 int 保存为 Big-Endian 才能正确。 (3认同)

Did*_*set 15

此警告对于错误地写入'test'应该写入的程序员很有用"test".

这种情况比实际需要多字符int常量的程序员更常发生.

  • 这是一个很好的例子,但是当我真的想写'test'并且有警告时会发生什么.我的代码中没有任何警告...... (3认同)
  • 您必须应对警告,或者找到您的编译器选项来禁用此特定警告(这可能会在代码的其他地方伤害您;-))。 (2认同)
  • 另一个偶然的程序员错误是错误记住十六进制转义的语法,当写一个'\ x61'时写'\ 0x61'. (2认同)

blu*_*ift 13

如果你很高兴你知道你正在做什么并且可以接受可移植性问题,例如你可以在GCC上禁用警告:

-Wno-multichar
Run Code Online (Sandbox Code Playgroud)

我将此用于我自己的应用程序,以便出于类似的原因使用AVI和MP4文件头.

  • @佩里恭喜!这是您在这个问题上第八次提到可移植性问题(包括我的回答中的一个)。 (3认同)

sqr*_*163 8

最简单的 C/C++ 任何编译器/标准兼容解决方案,@leftaroundabout 在上面的评论中提到:

int x = *(int*)"abcd";
Run Code Online (Sandbox Code Playgroud)

或者更具体一点:

int x = *(int32_t*)"abcd";
Run Code Online (Sandbox Code Playgroud)

另一种解决方案,也符合 C99 以来的 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");
Run Code Online (Sandbox Code Playgroud)

这里匿名联合用于为所需的数字结果提供一个很好的符号名称,“abcd”字符串用于初始化复合文字(C99)的左值。

  • 这**不**符合标准,因为它破坏了严格的别名。 (2认同)

o11*_*11c 7

即使您愿意查找您的实现定义的行为,多字符常量仍会随字节顺序而变化。

最好使用 (POD) struct { char[4] }; ...然后使用像 "WAVE"_4cc 这样的 UDL 来轻松构建该类的实例

  • @fuzzyTew: constexpr std::uintmax_t 运算符 ""_cc (char const * cc,std::size_t 大小) { std::uintmax_t val = 0; for (int i = 0; i != size; ++i) { val <<= 8; val += cc[i]; 返回值;} (2认同)