c - "-1>>5;"是 C 中的未指定行为吗?

标签 c gcc bit-manipulation language-lawyer unspecified-behavior

C11 §6.5.7 第 5 段:

The result of E1 >> E2 is E1 right-shifted E2 bit positions. If E1 has an unsigned type or if E1 has a signed type and a nonnegative value, the value of the result is the integral part of the quotient of E1 / 2*^E2. If E1 has a signed type and a negative value, the resulting value is implementation-defined.

但是,viva64引用文件说:

int B;
B = -1 >> 5; // unspecified behavior

我在 GCC 上运行了这段代码它总是给出输出 -1

因此,标准说的是“如果 E1 具有带符号的类型和负值,则结果值是实现定义的”,但该文档说的是 -1>>5; 未指定的行为

那么,-1>>5; 是 C 中的未指定行为吗?哪个是正确的?

最佳答案

两者都是正确的。实现定义的行为是一种特定类型的未指定行为。

引用 the C standard 的第 3.4.1 节它定义了“实现定义的行为”:

1 implementation-defined behavior

unspecified behavior where each implementation documents how the choice is made

2 EXAMPLE An example of implementation-defined behavior is the propagation of the high-order bit when a signed integer is shifted right.

来自第 3.4.4 节定义“未指定行为”:

1 unspecified behavior

use of an unspecified value, or other behavior where this International Standard provides two or more possibilities and imposes no further requirements on which is chosen in any instance

2 EXAMPLE An example of unspecified behavior is the order in which the arguments to a function are evaluated.

至于 GCC,您总是会得到相同的答案,因为操作是实现定义的。通过符号扩展实现负数右移

来自GCC documentation :

The results of some bitwise operations on signed integers (C90 6.3, C99 and C11 6.5).

Bitwise operators act on the representation of the value including both the sign and value bits, where the sign bit is considered immediately above the highest-value value bit. Signed >> acts on negative numbers by sign extension.

As an extension to the C language, GCC does not use the latitude given in C99 and C11 only to treat certain aspects of signed << as undefined. However, -fsanitize=shift (and -fsanitize=undefined) will diagnose such cases. They are also diagnosed where constant expressions are required.

关于c - "-1>>5;"是 C 中的未指定行为吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/46777286/

相关文章:

在 C 中使用 scanf 时,代码不会编译或抛出错误,永远陷入构建困境

gcc - 为 Julia 中的 C lib 使用构建 C 包装器

c - 可移植地将二进制补码整数写入内存的算法

c - 在 C 中通过管道将一个命令的输出作为另一个命令的输入

c - 将函数数组(带参数)作为参数传递给函数

c - 将用户输入存储到数组中

c - 强制两个无符号字符合并

c++ - 作为副作用的变量声明

c - 是否应该在每个声明中使用关键字 "inline"?

java - 反转 int 中的所有位并返回 int