Ian*_*ton 105 c label constants switch-statement
我正在阅读一些模拟器代码,我反驳了一些奇怪的东西:
switch (reg){
case 'eax':
/* and so on*/
}
Run Code Online (Sandbox Code Playgroud)
这怎么可能?我以为你只能switch
在积分类型上.是否有一些宏观技巧在继续?
Bat*_*eba 145
(只有你可以回答"宏诡计"部分 - 除非你粘贴更多的代码.但是这里没有太多的宏可以继续工作 - 正式你不允许重新定义关键字 ;这样做的行为是未定义的.)
为了实现程序可读性,诙谐的开发人员正在利用实现定义的行为.'eax'
是不是一个字符串,而是一个多字符常量.请仔细注意周围的单引号字符eax
.很可能它会int
在你的情况下为你提供一个独特的角色组合.(通常每个字符占32位的8位int
).每个人都知道,你可以switch
上int
!
最后,标准参考:
C99标准说:
6.4.4.4p10:"包含多个字符(例如,'ab')的整数字符常量的值,或包含未映射到单字节执行字符的字符或转义序列的值是实现定义的. "
Vla*_*cow 44
根据C标准(6.8.4.2开关声明)
3 每个case标签的表达式应为整数常量表达式 ...
和(6.6常量表达式)
6 整数常量表达式应具有整数类型,并且只能具有整数常量的操作数,枚举常量, 字符常量,结果为整数常量的sizeof表达式,以及作为强制转换的直接操作数的浮点常量.整数常量表达式中的转换运算符只能将算术类型转换为整数类型,除非作为sizeof运算符的操作数的一部分.
现在是什么'eax'
?
C标准(6.4.4.4字符常量)
2整数字符常量是用单引号括起来的一个或多个多字节字符的序列,如'x'中所示...
因此,'eax'
根据同一部分的第10段,它是整数字符常量
- ...包含多个字符(例如,'ab')的整数字符常量的值,或包含未映射到单字节执行字符的字符或转义序列的值是实现定义的.
因此,根据第一个提到的引用,它可以是整数常量表达式的操作数,可以用作案例标签.
注意字符常量(用单引号括起来)具有类型,int
并且与具有字符数组类型的字符串文字(用双引号括起来的字符序列)不同.
Sti*_*mer 12
正如其他人所说,这是一个int
常数,其实际值是实现定义的.
我假设代码的其余部分看起来像
if (SOMETHING)
reg='eax';
...
switch (reg){
case 'eax':
/* and so on*/
}
Run Code Online (Sandbox Code Playgroud)
您可以确定第一部分中的'eax'与第二部分中的'eax'具有相同的值,因此一切正常,对吧?......错了.
在评论中@Davislor列出了'eax'的一些可能值:
...
0x65
,0x656178
,0x65617800
,0x786165
,0x6165
,或别的东西
注意第一个潜在价值?那就是'e'
,忽略其他两个角色.问题是程序可能使用'eax'
,'ebx'
等等.如果所有这些常量具有与'e'
最终结果相同的值
switch (reg){
case 'e':
...
case 'e':
...
...
}
Run Code Online (Sandbox Code Playgroud)
这看起来不太好,是吗?
关于"实现定义"的好处是程序员可以检查他们的编译器的文档,看看它是否对这些常量做了明智的事情.如果有,家免费.
糟糕的是,其他一些可怜的家伙可以接受代码并尝试使用其他编译器进行编译.即时编译错误.该程序不可移植.
正如@zwol在评论中指出的那样,情况并不像我想象的那么糟糕,在不好的情况下代码无法编译.这至少会为您提供问题的确切文件名和行号.不过,你还没有工作计划.