【发布时间】:2017-06-05 09:26:50
【问题描述】:
我正在处理一个我想成为多平台的程序中的边缘情况。这是问题的摘录:
#include <stdio.h>
#include <string.h>
void print_bits(size_t const size, void const * const ptr){
unsigned char *b = (unsigned char*) ptr;
unsigned char byte;
int i, j;
for (i=size-1;i>=0;i--)
{
for (j=7;j>=0;j--)
{
byte = (b[i] >> j) & 1;
printf("%u", byte);
}
}
puts("");
}
int main() {
char* ascii = "0x80000000";
int myint = strtol(ascii, NULL, 16);
printf("%s to signed int is %d and bits are:\t", ascii, myint);
print_bits(sizeof myint, &myint);
return 0;
}
所以当我在 Linux 上使用 GCC 编译时,我会得到以下输出:
0x80000000 to signed int is -2147483648 and bits are: 10000000000000000000000000000000
在 Windows 上,使用 MSVC 和 MinGW 我得到:
0x80000000 to signed int is 2147483647 and bits are: 01111111111111111111111111111111
我认为 GCC 输出了正确的预期值。我的问题是,这种差异从何而来,如何确保在所有编译器上我得到正确的结果?
更新
这段代码背后的原因是,我必须检查 HEX 值的 MSB(#31 位)是 0 还是 1。然后,我必须得到接下来 7 位的无符号整数值(#30 到#24) 结果(如果是0x80000000这7位应该导致0:
int msb_is_set = myint & 1;
uint8_t next_7_bits;
next_7_bits = myint >> 24; //fine on GCC, outputs 0 for the next 7 bits
#ifdef WIN32 //If I do not do this, next_7_bit will be 127 on Windows instead of 0
if(msb_is_set )
next_7_bits = myint >> 1;
#endif
附:这是在同一台机器上(i5 64bit)
【问题讨论】:
-
"MinGW" 是 gcc 。
-
您能解释一下您期望在所有平台上的行为,更重要的是,为什么?
int可以是 16 位以上的任意大小,long可以是 32 位以上的任意大小,并且某些平台可能不使用 2 的补码 -
另外,您会使用包含前导
-符号的输入吗? -
注意。由于在范围内没有原型的情况下调用
strtol,此代码违反了约束,您的编译器都应该对此进行诊断(如果没有,则重新考虑您的编译器开关)。 (在 C89 中,这是未定义的行为,无需诊断) -
对平台做出共同假设;根据 C 标准,您的 MSVC 输出是正确的,并且“gcc on linux”是实现定义的
标签: c gcc visual-c++ bit-manipulation strtol