例如在C语言中,为什么位移运算的第二个操作数可以是有符号数?

5
注意:这个问题涉及到位移操作符<<和>>的第二个操作数的有无符号性,而与第一个操作数无关。
根据CERT INT34-C的部分内容:不要将负数位移...
并非需要证明,但他们证明了这是未定义行为
我本来认为这个规则很简单,因为如果你想向另一个方向进行位移,就使用适当的位移操作符以正数位移。
所以,在C中,通过负数位移既不必要也是未定义的,为什么<<或>>的第二个操作数甚至可以是带符号的?
MISRA-C:2004在其第6.10.2节中指出,无论您对MISRA的看法如何,作为解释结果类型仅依赖于第一个操作数的副作用,它说“第二个操作数可以是任何有符号或无符号整数类型”。[我强调的]。
为什么要邀请人们使用带符号的第二个操作数进行位移?为什么要允许它?是否有任何编译器会发出警告?

它可以是一个正式签名的类型,但不允许为负数,也不能大于类型中的位数。这是否意味着 C 应该要求使用 5 位宽的位域类型作为 32 位整数上移操作的右操作数?当然,那是无稽之谈。如果你不想要一种“引导”你做傻事的语言,那么你应该考虑寻找另一种语言。但其他语言会“引导”你去做不同的愚蠢之事(例如字符串连接),你很难找到“完美”的语言... - R.. GitHub STOP HELPING ICE
@R 确实我不能寻找完美的编程语言,但是在位移操作的第二个操作数上有两个要求之间存在差异:非负要求可以通过操作数的声明类型(而不是强制转换)来强制执行,而不太大的要求则需要实际检查操作数的值。 - talkaboutquality
1个回答

4

我无法确切地解释为什么事情会变成这样...但我很高兴我可以通过有符号值进行移位:

a <<= 3;表达式中的3是一个整数。
如果用int进行移位是非法的,那么你必须使用a <<= 3U;

禁止使用有符号值进行移位将破坏大量(我的意思是很多)代码!


成本:在复杂的移位表达式中可能会降低可读性(但应该避免这种情况,以提高可读性)。好处:保证移位计数不能为负数(防止编写行为未定义的代码)。那么,如果禁止有符号移位计数,会有什么问题呢? - talkaboutquality
@talkaboutquality: 现在考虑 int a; ... b << a;。如果 a 是负数,那就有问题了。将其改为 (unsigned)a 不会有任何帮助,因为 (unsigned)a 将是一个非常大的数字,而 (unsigned)a 的左移将导致未定义的行为。 - David Thornley
@david-thornley 当然我并不是要允许将类型转换为无符号数,而只是最初声明第二个操作数为无符号数。不确定编译器是否能够发出警告并要求这样做。也许更好的参考资料是 https://www.securecoding.cert.org/confluence/display/seccode/INT13-C.+Use+bitwise+operators+only+on+unsigned+operands 特别是其中@pmg 的例外情况 "INT13-EX2:如果移位运算符的右操作数在编译时已知,则可以使用带符号类型表示该值,前提是它是正数。" - talkaboutquality

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