负数在内存中是如何存储的?如何知道位表示法?

3
我了解MSB、LSB、补码等概念。现在,如果我写一个程序进行位操作,我该如何检查内存中实际的位级数据呢?
例如:int a = -1;,我该怎么知道它在4位表示中是10011110还是1111
我该如何确定我的实现方法用于表示负数?
我正在寻找一种检查C程序位级数据的方法。
我当前使用的平台是Ubuntu 12.04 LTS。再次强调,问题不是如何完成,而是如何找出或证明已经以某种方式完成。

2
可能是 1111(仅供参考)。但这取决于机器。 - Alex Lockwood
是的,这取决于情况。这就是为什么我想知道如何弄清楚我的机器是如何工作的。 - San
1
@AlexLockwood,实际上可能是1111而不是1110。 - Matt
@Matt,刚刚修复了那个问题哈哈,谢谢。 - Alex Lockwood
8个回答

3
union { int i; unsigned u; } x;
x.i = -1;

现在,x.u会给你一个相同位数的无符号整数。表示无符号数字只有一种方法,因此您可以检查它。(提示:最可能是二进制补码。)
printf("%x\n", x.u);

以上打印语句会打印出无符号整数的十六进制表示,你可以使用它来确定位。


2
在表示无符号数的方式上只有一种方法是不正确的。例如,在硬件设计中,您经常会发现格雷编码数字。 - flolo

1
一种简单的方法是像这样在调试器中检查变量:
(gdb) p/t var

p/t 表示打印二进制表示。


1
void showBit(int num, int nBit)//nBit -> number of bits
{
    unsigned int temp = 1<<(nBit-1), i;

    for(i=0; i<nBit; ++i)
    {
        printf("%d ", ((num&temp)?1:0) );
        temp = temp>>1;
    }
    printf("\n");
}  

你可以使用这个函数来打印二进制表示。在ideone上查看。


1
在C语言中,负数采用二进制补码格式表示有符号数。
这么做是为了避免编译器的问题(即使int是8位、16位或32位等,也可以工作)。
在你的情况下,如果编译器将int解释为8位,则会存储1111 1111。一旦第一个位(符号位)为1,编译器就会理解它是一个负数,并且理解这个数字必须是二进制补码,也就是带有负号的0000 0001。

C语言支持不同的表示负数的方式。目前最流行的是二进制补码,肯定也是OP系统使用的一种方式,但并非必须。 - chqrlie

1
通过应用位运算。例如,您可以通过执行a & (1<<n)来测试第n位是否设置(在循环中应用它,然后您就得到了整个数字)。 编辑:但是,这仅适用于内部表示为二进制的情况。当使用不同的系统(例如,俄罗斯在70年代拥有一台三进制和数字系统的计算机,而波兰则采用负二进制基础的系统)时,这将无法给出正确的内部使用格式。

移位操作是否与计算机或它们所作用的数字的符号有关?它们是否会移动符号位?我对位运算本身有很多问题! - San
@San 右移操作可能会受整数的有符号性影响。左移操作无论如何都是相同的。 - Matt

0

你甚至可以使用联合体

union num
{
    int f;
    char c[4];
};

void printBinary(union num u)
{
    int i,t,j;

    for(i=sizeof(u)-1; i>=0; i--)
    {
            for(j=0,t=128; j<8; j++,t>>=1)
                    printf("%d",(u.c[i]&t)?1:0);
            printf(" ");
    }
}

int main() 
{
    union num n;
    n.f=10;
    printBinary(n);
    return 0;
}

请看这里:http://ideone.com/i9YCt


0
我该如何确定我的实现使用哪种方法来表示负数?
以下是方法:
unsigned int a = -1;
swicth (a & 3U)
{
    case 3:
        printf("two's complement\n");
        break;

    case 2:
        printf("one's complement\n");
        break;

    case 1:
        printf("sign and magnitude\n");
        break;

    default:
        printf("compiler broken\n");
        break; 
}

最终答案实际上在您的编译器文档中,该文档需要记录使用的有符号表示。例如,对于gcc

有符号整数类型是使用补码、反码还是原码表示,以及非常规值是陷阱表示还是普通值(C99 6.2.6.2)

GCC仅支持补码整数类型,并且所有位模式都是普通值。

http://gcc.gnu.org/onlinedocs/gcc/Integers-implementation.html


0

数字的第8位表示正负。如果第8位是0,则为正数,否则为负数。

For example x=8
so In binary x=8=0000 1000 (It is positive number, so eight bit is 0 from right to left)

For negative x = -8
The negative numbers are represented in binary using 2's complement usually.
 so x = -8 

step 1 binary of        8 = 0000 1000
step 2 1's complement     = 1111 0111
step 3 2's complement     =         1
                         y = 1111 1000 =248(so it represents the negative because 8th bit is 1 then it follows the below formula)

The formula for getting negative value from binary representation is 2^8-y
 so 256-248=8

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