字符常量是否始终为正?

时间:2019-05-30 19:16:06

标签: c language-lawyer

我很好奇我是否可以编译

int map [] = { [ /*(unsigned char)*/ 'a' ]=1 };

无论平台如何,还是在将其用作索引之前将字符常量强制转换为unsigned char都比较好。

2 个答案:

答案 0 :(得分:7)

如果字符常量基于基本执行时字符集的成员,则它是int的正值。

由于a位于该基本字符集中,因此我们知道'a'必须是肯定的。

例如,'\xFF'可能不是正数。 FF的值将被视为char 的位模式,可以对其进行签名,由于二进制补码,因此为-1。如果我们使用对应于类型char的负值的字符而不是数字转义,则将采用类似的推理,例如与8位系统上的0x80-0xFF字节范围相对应的字符。

就像ANSI C89和C90中那样,我依赖于内存;但是这些要求在新的草案和标准中仍然存在。在n1570草案中,我们有以下项目:

  1. 6.4.4.4字符常量,第10段:”如果整数字符常量包含单个字符或转义序列,则其值是当char类型的对象的值等于单个字符或转义序列将转换为int类型。”

  2. 6.2.5类型,第3段:“如果基本执行字符集的成员存储在char对象中,则其值必须保证为非负数。”

字符常量不是“ char对象”,但是6.4.4.4中的要求指定了使用char表示形式确定字符常量的值:”。一个对象,其类型为char类型,其值为...“


†​​无前缀字符常量的数字转义序列和以L前缀的数字转义序列具有关联的“对应类型”,该类型是无符号的,并且必须在该类型的范围内(6.4.4.4 9) 。想法是将字符值指定为无符号值,该值给出其按位表示,然后将其解释为char。示例2(6.4.4.4 13)中也传达了这一意图。

答案 1 :(得分:4)

  

我很好奇我是否可以编译

int map [] = { [ /*(unsigned char)*/ 'a' ]=1 };
     

无论平台如何还是投射字符常量是否更好   将未签名的char用作索引之前。

您的特定代码是安全的。

'a'是一个整数字符常量。语言指定了这些

  

一个整数字符常量的类型为int。整数值   字符常量,包含一个映射到   单字节执行字符是   映射字符的表示形式,解释为整数。 [...]   如果整数字符常量包含一个   单个字符或转义序列,其值就是结果   当类型为char的对象的值是单个对象的对象时   字符或转义序列将转换为int类型。

C2011, paragraph 6.4.4.4/10

它进一步指出了

  

如果基本执行字符集的成员存储在char对象中,则其值将确保为非负数。

C2011, paragraph 6.2.5/3

,并且在每个实现中都要求基本源字符集和基本执行字符集都包含小写拉丁字母,包括“ a”。 (C2011, paragraph 5.2.1/3

但是,您应该注意:不是基本执行字符集成员的字符的整数字符常量,包括多字节字符,或多字符整数字符常量不一定非负。从原理上讲,其中某些甚至在默认char是无符号类型的机器上也为负。

此外,再次考虑多字节字符,强制转换为unsigned char也不一定是安全的,因为这样可能会产生冲突。为确保避免冲突,您需要将其转换为unsigned int,但这会产生比预期更大的 个数组。如果您坚持使用基本字符集,则可以。如果您坚持使用单字节字符,则可以进行强制转换。如果必须容纳多字节字符,那么为了可移植性,您可能应该选择其他方法。