C中“大”字符十六进制常量的值是多少?

时间:2013-09-08 00:28:36

标签: c char integer c99 c11

假设我们在C中写下以下字符常量:

  '\xFFFFAA'  

它的数值是多少?

标准 C99 说:

  • 字符常量的类型为int
  • 十六进制字符常量可以表示为unsigned char
  • 基本字符常量的值是非负的。
  • 任何字符常量的值都在char的范围内。

此外:

  • signed char的值范围包含在int的值范围内。
  • charunsigned charsigned char的大小(以位为单位)相同:1个字节。
  • 字节的大小由CHAR_BIT给出,其值至少为8.

我们假设我们有CHAR_BIT == 8的典型情况 另外,我们假设char对我们来说是signed char

通过以下的规则:常数 '\ xFFFFAA' 具有输入int,但其在unsigned char,althoug其的实际值的值的可以表示 适合char 根据这些规则,'\ xFF'的示例将为我们提供:

  (int)(char)(unsigned char)'\xFF' == -1

第一个演员unsigned char来自“,可以表示为unsigned char”要求。
第二个演员char来自“值适合char”要求 第3个演员int来自“has type int”要求。

但是,常量'\xFFFFAA'太大,无法“代表”为unsigned int
它的价值是什么?

我认为该值是(char)(0xFFFFAA % 256)的结果,因为标准或多或少地说明了以下内容:

  • 对于无符号整数类型,如果某个值大于可由该类型表示的最大 M ,则该值是在取余数模数 M 后获得的。

我对这个结论是对的吗?

修改我已经说服了 @KeithThompson :他说,根据标准,一个很大的十六进制字符常量是违反约束
所以,我会接受这个答案。

但是:例如,对于GCC 4.8,MinGW,编译器会触发警告消息,程序将按照我所描述的行为进行编译。因此,它被视为有效的常数,如'\ x100020',其值为0x20。

2 个答案:

答案 0 :(得分:4)

C标准定义了6.4.4.4节中的语法和语义。我将引用C11标准的N1570草案。

第6段:

  

反斜杠后面的十六进制数字和a中的字母 x   十六进制转义序列被视为构造的一部分   单个字符的整数字符常量或单个字符   宽字符常数。的数值   这样形成的十六进制整数指定了所需的值   性格或广泛的性格。

第9段:

  

<强>约束

     

八进制或十六进制转义序列的值应在   相应类型的可表示值范围:

后跟一张表说没有前缀,“对应的类型”是unsigned char

因此,假设0xFFFFAA超出类型unsigned char的可表示范围,则字符常量'\xFFFFAA'是违反约束的,需要编译时诊断。编译器可以完全拒绝您的源文件。

如果您的编译器至少没有警告过您,那么它就不符合C标准。

是的,标准确实说无符号类型具有模块化(环绕)语义,但这仅适用于算术表达式和一些转换,而不适用于常量的含义。

(如果您的系统上有CHAR_BIT >= 24,则完全有效,但这种情况很少见;通常为CHAR_BIT == 8。)

如果编译器选择仅发出警告然后继续编译源代码,则行为未定义(仅仅因为标准没有定义行为)。

另一方面,如果您实际上意味着'xFFFFAA',则不会将其解释为十六进制。 (我认为这只是一个错字,问题已被编辑以纠正它,但无论如何我都会留在这里。)它的值是实现定义的,如第10段所述:

  

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

包含多个字符的字符常量是一种几乎无用的语言功能,偶然使用它比故意使用它们更多。

答案 1 :(得分:1)

是的,\xFFFFAA的值应由unsigned char表示。

6.4.4.4 9约束

  

八进制或十六进制转义序列的值应在   for的unsigned char类型的可表示值范围   整数字符常量。

但C99也说,

6.4.4.4 10语义

  

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

因此,结果值应该在unsigned char([0,255],如果CHAR_BIT == 8)的范围内。但至于哪一个,它取决于编译器,架构等。