如何用包含三个八进制数字的比特模式表示一个字符?

4

从K&R关于C编程语言的第二章(子章节2.3命名为常量):

某些字符可以通过转义序列(如\n代表换行符)在字符和字符串常量中表示;这些序列看起来像两个字符,但实际上只表示一个字符。此外,任意字节大小的位模式可以被指定为

′\ooo′

其中 ooo 为一到三个八进制数字(0...7)

′\xhh′

其中hh是一个或多个十六进制数字(0...9,a...f,A...F)。因此我们可以写成
#define VTAB ′\013′    /* ASCII vertical tab */
#define BELL ′\007′    /* ASCII bell character */

or, in hexadecimal,
#define VTAB ′\xb′     /* ASCII vertical tab */
#define BELL ′\x7′     /* ASCII bell character */

我困惑的部分是以下措辞(强调我):其中ooo是一个到三个八进制数字(0...7)。如果有三个八进制数字,则所需的位数将为9(每个数字3位),这超出了字符所需的字节长度。我一定是漏了什么。我错过了什么?

2
超过所需字符字节长度的内容是错误的。机器可以拥有9位字符,或7位,甚至16位。'\377'只是常量,用作初始化器。如果这些值无法适应机器字符,编译器总是会发出警告。 - wildplasser
3个回答

4
\ooo(3个八进制数字)确实可以指定0到111111111(二进制)或511的9位值。是否允许取决于char大小。
如下所示的赋值在许多环境中会生成警告,因为在这些环境中char是8位的。通常允许的最高八进制序列是\377。但是,一个char并不一定是8位。OP的"9...超过了字符所需的字节长度"是不正确的。
char *s = "\777";  //warning "Octal sequence out of range"
char c  = '\777';  //warning
int i   = '\777';  //warning

在通常使用ASCII的环境中,三位八进制数常量'\141''a'相同。但是在另一种字符集中,'a'可能是不同的。因此,如果需要可移植的01100001位模式赋值,则可以使用'\141'而不是'a'。同样地,也可以通过赋值'\x61'来实现相同的效果。在某些情况下,八进制模式可能更合适。

C11 6.4.4.4.9如果未使用前缀,“八进制或十六进制转义序列的值必须在相应类型的可表示值范围内:无符号字符”


为什么 int i = '\777'; 应该生成一个警告? - Geek
1
@Geek '\777' 可能会自行生成警告。它试图表示一个 char,但超出了 8 位 char 的范围。事实上,int 可以容纳 9 位以上,不是警告的来源。但可以这样做:int i = 0777(没有 ')。 - chux - Reinstate Monica

0

如果我们谈论的是八位字节,那么第一个八进制数字只允许到3(两位),而不是7(三位)。如果我们谈论的是ASCII(7位值),那么第一个数字只能是零或一。

如果K&R说得不同,那么他们的描述要么不完整,要么不正确。


为什么呢?你能详细说明一下吗? - Geek
你已经说明了原因:一个字节只能容纳八个位。实际上,由于我们正在讨论ASCII,因此第一个数字只能是零或一,因为ASCII定义在7位上,而不是8位。 - Robert Harvey
我认为在K&R或以后的C标准中都没有提到ASCII。据我所知,字符集只需要容纳字母,数字和NUL即可。为了支持EBDIC等,采取了许多预防措施。 - wildplasser
@wildplasser:好的,但是限制条件仍然存在。 - Robert Harvey

0

据我记得,K&R没有定义字符的代码数字范围。在早期,通常是ASCII范围0...127。现在通常是8位范围0...255,但也可能更宽。无论如何,char数据类型上的实现定义限制也意味着对转义符号的限制。

例如,如果范围是0...127,则\177是允许的最大八进制转义。


FYI:目前C11 5.2.4.2.1“不是位域的最小对象的位数(字节)”>=8(CHAR_BIT)。 - chux - Reinstate Monica

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接