我有一个int x。为简单起见,假设ints 占据范围 -2^31 到 2^31-1。我想计算2*x-1. 我允许x为任何值 0 <= x<= 2^30。如果我计算 2*(2^30),我会得到 2^31,这是整数溢出。
一种解决方案是计算2*(x-1)+1. 比我想要的多了一项减法,但这不应该溢出。但是,编译器会将其优化为2*x-1. 这是源代码的问题吗?这是可执行文件的问题吗?
这是 Godbolt 的输出2*x-1:
func(int): # @func(int)
lea eax, [rdi + rdi]
dec eax
ret
Run Code Online (Sandbox Code Playgroud)
这是 Godbolt 的输出2*(x-1)+1:
func(int): # @func(int)
lea eax, [rdi + rdi]
dec eax
ret
Run Code Online (Sandbox Code Playgroud) c++ integer-overflow compiler-optimization undefined-behavior integer-arithmetic
新的C++标准仍然拒绝指定整数类型的二进制表示.这是因为C++的实际实现不使用2的补码算法吗?我觉得很难相信.是不是因为委员会担心硬件的未来发展会让"过时"的概念变得过时?再次难以置信.任何人都可以对此有所了解吗?
背景:我在一个评论帖中惊讶两次(Benjamin Lindley对这个问题的回答).首先,来自piotr的评论:
签名类型的右移是未定义的行为
其次,来自James Kanze的评论:
当分配给long时,如果该值不适合long,则结果是实现定义的
在我相信之前,我必须在标准中查看这些内容.它们的唯一原因是适应非二进制补码整数表示.为什么?
我正在开发一个游戏,我发现自己经常检查某些数量是否代表我的世界的向量所接受的索引范围:
if(a >= 0 && a < 16 && b >= 0 && b < 16 && c >= 0 && c < 16 &&
d >= 0 && d < 16 && e >= 0 && e < 16)
{
//do things with vector[a][b][c][d][e]
}
Run Code Online (Sandbox Code Playgroud)
我经常要检查比这更多的条件.有没有办法让这些检查更简洁和/或更容易阅读?
或者,有没有办法可以避免完全进行检查?矢量是16x16x16x16x16; 我可以这么做,如果我给它一个16作为索引,它会做什么,而不是段错误?
有没有人知道C标准支持的任何平台,对于这些平台仍然有积极的开发工作,但它们是:
编辑:或者,如果1995年至1998年期间有平台影响了C99决定包括上述内容,但已停止使用,我也会对它们感兴趣.
编辑:C理由有关填充位的说法:
填充位是用户可访问的无符号整数类型.例如,假设一台机器使用一对16位短路(每个都有自己的符号位)来构成一个32位的int,并且当在这个32位int中使用时,忽略较低short的符号位.然后,作为32位有符号整数,在确定32位有符号int的值时会忽略一个填充位(在32位的中间).但是,如果将此32位项目视为32位无符号整数,则该填充位对用户程序可见.C委员会被告知有一台机器以这种方式工作,这就是填充位被添加到C99的一个原因.
脚注44和45提到奇偶校验位可能是填充位.委员会不知道任何具有用户可访问的奇偶校验位的机器在整数内.因此,委员会不知道任何将奇偶校验位视为填充位的机器.
所以另一个问题是,C99提到的那台机器是什么?
编辑:看来,C99正在考虑消除对1的补支持和符号的振幅:http://www.open-std.org/jtc1/sc22/wg14/www/docs/n868.htm HTTP://www.open- std.org/jtc1/sc22/wg14/www/docs/n873.htm(搜索6.2.6.2)
我正在阅读C++编程语言,其中Stroustrup声明char的int值可以在0到255或-127到127之间,具体取决于实现.它是否正确?它似乎应该是从-128到127.如果不是,为什么在第二种实现可能性中它们只有255个可能的值,而不是256.
最近我对这个问题很困惑.也许是因为我没有阅读语言规范(这是我的错,我知道).
C99标准没有说明编译器应该使用哪个负数表示.我一直认为存储负数的唯一正确方法是两个补码(在大多数情况下).
所以这是我的问题:您是否知道任何现在的编译器默认实现一个补码或符号幅度表示?我们可以用一些编译器标志更改默认表示吗?
确定使用哪种表示的最简单方法是什么?
那么C++标准呢?
请查看以下代码并帮助我理解它
int a=1;
int b=~1;
printf("%d",b);
Run Code Online (Sandbox Code Playgroud)
输出是:
-2
Run Code Online (Sandbox Code Playgroud)
所以这表示 1=(00000001) 当经历 ~ 时产生 (11111110),它是数字 2 的 2 补码,因此 -2 就是答案。那么 100 总是被假定为 -4 而不是 4 ?
我正在阅读一些 Windows API 头文件,我看到了一些我不明白的代码:
typedef void *HANDLE;
typedef HANDLE DPI_AWARENESS_CONTEXT;
#define DPI_AWARENESS_CONTEXT_UNAWARE ((DPI_AWARENESS_CONTEXT)-1)
Run Code Online (Sandbox Code Playgroud)
从void *typedef 中减去一个值是什么意思?