签名与无符号数字0xFFFFFFFF歧义?

时间:2016-03-18 15:23:43

标签: c# c++ binary

正如你在这里看到的,我有一个无符号变量和一个带有相同二进制值但不同小数结果的带符号变量。

 uint unsigned = 0xFFFFFFFF; // 4,294,967,295
 int signed = 0xFFFFFFFF;    // -1

我真的很困惑!在所有32/64位全部打开之后,机器如何区分有符号和无符号。是否有完全用于此的 CPU 标志? CPU如何知道未签名签名号码之间的区别?试着理解这几个小时的概念!

或者......另一个例子......让我们拿4位:

// 1 1 0 1  <--- -3
// 0 0 1 0  <---  2

如果我们从-3减去2,结果将是:

// 1 0 0 1  <--- -1 or 9???

cpu将产生该结果,但我的应用程序如何知道它是-1还是9?在编译时已知预期的结果类型?

另一个例子......

    int negative = -1;
    Console.WriteLine(negative.ToString("X")); //output FFFFFFFF
    uint positive = 0xFFFFFFFF;
    Console.WriteLine(positive.ToString("X")); //output FFFFFFFF
  

稍后编辑:

我对这些东西搞砸了一点,我想我明白了,如果我错了请纠正我: 我们有以下示例:

    sbyte positive = 15;                          //0xF   ( 0000 1111)
    sbyte negative = unchecked((sbyte)-positive); //0xF01;( 1111 0001)

    sbyte anotherPositive = 7;                    //0x7   ( 0000 0111)

    sbyte result = (sbyte)(negative + anotherPositive); 
//The cpu will add the numbers 1111 0001                                                              
//                             0000 0111                                                     
//                             1111 1000   
// (Addition result is 248  but our variable is 
//SIGNED and we have the sign bit ON(1) so the the value will be interpreted as -8)

3 个答案:

答案 0 :(得分:8)

  

我真的很困惑!在所有32位全部打开之后,机器如何在低电平之间产生差异。

机器没有;编译器。编译器知道signedunsigned变量的类型(忽略了{C}和C ++中signedunsigned都是关键字的事实。因此,编译器知道要生成什么指令以及基于这些类型调用哪些函数。

类型之间的区别是在编译时进行的,根据编译时类型更改可能相同的原始数据的解释。

考虑打印变量值的示例。当你写

cout << mySignedVariable << " " << myUnsignedVariable << endl;

编译器看到正在应用<< operator的两个重载:

  • 第一个<<拨打ostream& operator<< (int val);
  • 第二个<<拨打ostream& operator<< (unsigned int val);

一旦代码到达正确的运算符实现,您就完成了:为特定重载生成的代码具有关于如何处理有符号或无符号值的信息&#34;烘焙到&#34;它的机器代码。采用int的实现使用带符号的机器指令进行比较,除法,乘法等,而无符号实现使用不同的指令,产生所需的结果。

答案 1 :(得分:1)

语言的类型系统的工作是解释它所看到的内容。

所有CPU真正看到的是一堆零和一些。

有趣的是,二进制补码算法可以使用与无符号算术相同的指令。一个补码算法需要一个烦人的补充减法器

答案 2 :(得分:0)

计算机并不关心,只要它关注它们都是相同的,它在计算机上运行的编译器和语言结构决定如何解释和处理位数组,并且它们知道它是否是一个uint,int ,double,single,unicode char等。

这就是为什么托管内存如此重要,如果您的程序将uint写入内存地址而另一个程序将其读取为char,则会出现各种奇怪的行为,这可以在记事本中打开二进制文件时看到