You need to enable JavaScript to run this app.
最新活动
大模型
产品
解决方案
定价
生态与合作
支持与服务
开发者
了解我们

C语言中0左移操作及特定左移表达式是否属于未定义行为的技术咨询

C语言中0左移操作及特定左移表达式是否属于未定义行为的技术咨询

嘿,这个问题问得很精准,咱们结合C标准来一步步拆解这两个表达式:

首先先明确C标准(以C17为例,C11及之前的版本规则一致)中关于移位运算符的核心规定:

根据C17标准6.5.7节(移位运算符)的描述:
3. 对两个操作数执行整数提升,结果的类型为提升后的左操作数类型。如果右操作数的值为负,或者大于等于提升后左操作数的宽度(即该类型的二进制位数),行为是未定义的。
4. E1 << E2 的结果是将E1左移E2位,空出的位用0填充。若E1为无符号类型,结果为E1×2E2对结果类型最大值加1取模;若E1为有符号类型且非负,且E1×2E2可被结果类型表示,则该值即为结果,否则行为未定义。

接下来逐个分析你的两个表达式:

  • 表达式 0 << 32
    这里的左操作数0默认是int类型,在绝大多数现代系统中int的宽度为32位。右操作数是32,刚好等于int类型的宽度。根据上述6.5.7节第3条规则,无论左操作数的值是什么,只要右操作数大于等于提升后左操作数的宽度,行为就属于未定义(UB)。虽然从逻辑直觉上0左移任何位还是0,但标准并没有给这种情况开特例,编译器可以自由处理(比如直接优化为0,或者触发其他行为),都符合标准要求。

  • 表达式 0LL << 64
    0LLlong long类型,通常该类型的宽度为64位。右操作数是64,等于long long的宽度。同样触发6.5.7节第3条的规则,这个表达式的行为也是未定义(UB)。理由和上面一致,标准不会因为左操作数是0就豁免移位位数的限制。

额外提一句:有些编译器在实践中可能会把这类表达式处理为0,但这只是编译器的扩展行为,并非C标准强制要求的,所以在写可移植的代码时绝对不能依赖这种行为。

备注:内容来源于stack exchange,提问作者lol lol

火山引擎 最新活动