这个源代码在C中打开一个string。它是怎么做到的?

我正在阅读一些模拟器代码,我已经反驳了一些很奇怪的东西:

switch (reg){ case 'eax': /* and so on*/ } 

这怎么可能? 我以为你只能switch积分types。 有一些macros观的诡计正在进行吗?

(只有你可以回答“macros观欺骗”的部分 – 除非你粘贴更多的代码,但是macros在这里没有太多的工作 – 在forms上你不能重新定义关键字 ,这样做的行为是不确定的。

为了实现程序可读性,机智的开发者正在利用实现定义的行为'eax' 不是一个string,而是一个多字符常量 。 请仔细注意eax周围的单引号字符。 在你的情况下,它最有可能给你一个int ,这对于这个字符组合是唯一的。 (通常每个字符在32位int占用8位)。 每个人都知道你可以switch一个int

最后,一个标准的参考:

C99标准说:

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

根据C标准(6.8.4.2 switch语句)

3 每个case标签的expression应该是一个整型常量expression式

和(6.6常量expression式)

6 一个整型常量expression式应该有整数types,只能有整型常量,枚举常量, 字符型常量 ,sizeofexpression式的结果是整型常量,浮点型常量是转换的立即操作数。 在整型常量expression式中转换运算符只能将算术types转换为整数types,除了作为sizeof运算符的操作数的一部分。

现在什么是'eax'

C标准(6.4.4.4字符常量)

2整数字符常量是一个或多个以单引号括起来的多字节字符序列 ,如'x'…

所以'eax'是根据同一部分第10段的整数字符常量

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

所以根据第一个提到的引用,它可以是一个整型常量expression式的操作数,可以用作一个case标签。

请注意,字符常量(用单引号括起来)的types为int ,与用字符数组types的string文字(用双引号括起来的字符序列)不同。

正如其他人所说,这是一个int常量,其实际值是实现定义的。

我假设代码的其余部分看起来像

 if (SOMETHING) reg='eax'; ... switch (reg){ case 'eax': /* and so on*/ } 

你可以肯定的是,第一部分中的'eax'和第二部分中的'eax'有相同的值,所以一切正常。 错了

在@Davislor评论中列出了一些可能的'eax'值:

0x656178或其他

注意第一个潜在的价值? 这只是'e' ,忽略了其他两个字符。 问题是程序可能使用'eax''ebx'等等。 如果所有这些常量与'e'具有相同的值,那么结果就是一样

 switch (reg){ case 'e': ... case 'e': ... ... } 

这看起来不太好,是吗?

关于“实现定义”的好处是程序员可以检查他们的编译器的文档,看看这些常量是否合理。 如果是的话,免费入住。

不好的部分是,其他一些可怜的人可以采取代码,并尝试使用其他编译器编译它。 即时编译错误。 该程序是不可移植的。

正如@zwol在评论中指出的那样,情况并不像我想象的那么糟糕,在糟糕的情况下代码不能编译。 这至less会给你一个确切的问题文件名和行号。 不过,你不会有一个工作计划。

该代码片段使用称为多字符字符常量的历史奇怪,也被称为多字符

'eax'是一个整数常量,其值是实现定义的。

以下是关于多字符的一个有趣的页面,以及如何使用它们,但不应该:

http://www.zipcon.net/~swhite/docs/computers/languages/c_multi-char_const.html


回头看后视镜,丹尼斯·里奇(Dennis Ritchie)最初的C手册( usr/dmr/www/cman.pdf )指定了字符常量。

2.3.2字符常量

字符常量是用单引号'' ' ''括起来的1或2个字符。 在一个字符常量内,一个单引号之前必须有一个反斜杠“ \ ”。 某些非graphics字符和“ \ ”本身可能会根据下表进行转义:

  BS \b NL \n CR \r HT \t ddd \ddd \ \\ 

\ddd ' \ddd '由反斜杠和1,2或3个八进制数字组成,这些八进制数字用于指定所需字符的值。 这种结构的一个特例是“ \0 ”(后面跟着一个数字),表示一个空字符。

字符常量的行为完全像整数(特别是不像字符types的对象)。 按照PDP-11的寻址结构,长度为1的字符常量在低位字节中具有给定字符的编码,在高位字节中具有0的编码。 长度为2的字符常量具有低字节中的第一个字符和高位字节中的第二个字符的代码。 具有多个字符的字符常量本质上是机器相关的,应该避免。

关于这个奇怪的结构,最后一个短语是你需要记住的: 字符常量与多个字符本质上是机器相关的,应该避免。