【问题标题】:Is a 64-bit character literal possible in C?C 中是否可以使用 64 位字符文字?
【发布时间】:2021-08-11 06:00:35
【问题描述】:

以下代码编译良好:

uint32_t myfunc32() {
    uint32_t var = 'asdf';
    return var;
}

以下代码给出警告,“字符常量对于它的类型来说太长了”:

uint64_t myfunc64() {
    uint64_t var = 'asdfasdf';
    return var;
}

确实,64 位字符文字被 GCC 截断为 32 位常量。 64 位字符文字不是 C 的特性吗?我找不到这方面的任何好信息。

编辑:我正在做更多的测试。事实证明,另一个编译器 MetroWerks CodeWarrior 可以按预期编译 64 位字符文字。如果这还不是 GCC 的一个特性,那么它确实应该是。

【问题讨论】:

  • 鉴于字符文字是int,并且大多数系统上的int 直接映射到int32_t,我认为这是有道理的......或者至少与使用一样有意义任何多字符文字(几乎没有)。
  • 这里只是推测,但可能会出现这种观察结果,因为 gcc 支持的最宽字符格式是 32 位 wchar_t(可以保存 UTF-32 字符)。
  • "如果这还不是 GCC 的一个特性,它确实应该是。"不...因为多字符转换的结果是实现定义的,所以无论如何都没有用。最好避开它们。
  • 只是一些疯狂的猜测,但添加ul 后缀是否有效?

标签: c gcc


【解决方案1】:

64 位字符文字不是 C 的特性吗?

确实不是。根据 C99 §6.4.4.4 第 10 点(第 73 页here):

整数字符常量的类型为int。整数字符常量的值 包含映射到单字节执行字符的单个字符是 被解释为整数的映射字符表示的数值。 包含多个字符的整数字符常量的值(例如, 'ab'),或包含不映射到单字节的字符或转义序列 执行字符,是实现定义的。

因此,字符常量的类型为int,在大多数现代平台上意味着int32_t。另一方面,由多字节字符常量产生的int 的实际值是实现定义,所以你不能对int x = 'abc'; 抱有太多期望,除非你的目标是特定的编译器和编译器版本。您应该避免在正常的 C 代码中使用此类语句。

根据 GCC 特定的行为,from the GCC documentation 我们有:

预处理器表达式中字符常量的数值。 预处理器和编译器以相同的方式解释字符常量;即,‘\a’ 等转义序列被赋予了它们在目标机器上的值。

编译器一次计算一个字符的多字符字符常量,将前一个值左移每个目标字符的位数,然后在截断到宽度的新字符的位模式中进行或运算的目标人物。最后的位模式给定类型int,因此是有符号的,不管单个字符是否有符号。 如果常量中的字符多于目标 int 中的字符数,编译器会发出警告,并忽略多余的前导字符。

例如,对于具有 8 位字符的目标,'ab' 将被解释为 ‘(int) ((unsigned char) 'a' * 256 + (unsigned char) 'b')’'\234a' 将被解释为 ‘(int) ((unsigned char) '\234' * 256 + (unsigned char) 'a')’

【讨论】:

  • 我认为可以肯定地说我正在编写疯狂的 C 代码。这是一个游戏改装项目,在原始代码中,32 位和 64 位字符文字经常用作实际字符串的替代品(可能是为了避免使用 strcmp)。遗憾的是 64 位字符文字不是 C 标准中的东西,但我会找到一些解决方法。感谢您快速简洁的回答。
  • @MintyMeeo 我不能说在你的情况下进行这样的优化是否有意义,但现代编译器应该已经能够在可能的情况下优化小字符串的比较。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2015-05-16
  • 2011-05-25
  • 1970-01-01
  • 2015-02-04
  • 2021-02-05
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多