假设我们在C中写下以下字符常量:
'\xFFFFAA'
它的数值是多少?
标准 C99 说:
int
。 unsigned char
。 char
的范围内。 此外:
signed char
的值范围包含在int
的值范围内。 char
,unsigned char
和signed 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)
的结果,因为标准或多或少地说明了以下内容:
我对这个结论是对的吗?
修改我已经说服了 @KeithThompson :他说,根据标准,一个很大的十六进制字符常量是违反约束
所以,我会接受这个答案。
但是:例如,对于GCC 4.8,MinGW,编译器会触发警告消息,程序将按照我所描述的行为进行编译。因此,它被视为有效的常数,如'\ x100020',其值为0x20。
答案 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)的范围内。但至于哪一个,它取决于编译器,架构等。