C语言打印16进制出现0xffffff现象的问题剖析!

其实类似的问题不是只在网络程序中才会出现的,看示例代码:

 

复制代码

  1 #include <stdio.h>

  2 int main()

  3 {

  4     char c = 0xc9;

  5     printf(“A:c = %2xn”,(unsigned char)c);

  6     printf(“B:c = %2xn”,c & 0xff);

  7     printf(“C:c = %2xn”,c);

  8     return 0;

  9 }

复制代码

  程序输出如下:

 

A:c = c9

B:c = c9

C:c = ffffffc9

  可以看到:

 

  把c转换成unsigned char打印是正确的。视作情况A。

 

  把c与 0xff做&操作后打印正确。视作情况B。

 

  对c不做任何处理,则问题复现了,打印出ffffffc9。视作情况C。

 

  情况A
B是我百度来的一些解决C现象的方法。那么我们现在来逐一分析解释ABC三种情况。

 

  

 

  首先我们必须知道,printf()函数的%x(X)输出的是Int型别的16进制格式。所以char型别的c变量会被转换成Int型别。

 

  其次,我们的知道计算机是用补码表示数据的。关于原码,反码,补码的知识请自行充电。

 

情况C:

 

   c的补码:11001001(0xc9)。

 

   c的反码:11001000(0xc9)。

 

   c的原码:10110111(0xc9)。 

 

   因为char型别是带符号的,所以最高位的1这里视为负号。

 

   把c转换成Int型别   char  —–> Int

 

   Int_c的原码:10000000 00000000 00000000
00110111(把c原码的最高位1  提到最高位。其余高位补0)。

 

   Int_c的反码:11111111 11111111 11111111 11001000

 

   Int_c的补码:11111111 11111111 11111111 11001001(0xffffffc9)。

 

   所以打印出来看似诡异的值其实是合情合理的。如何避免?看AB情况。

 

情况B:

 

  我们在情况C的基础上将c与0xff做&操作。

 

  Int_c的补码:11111111 11111111 11111111 11001001(0xffffffc9)。

 

         &

 

         00000000 00000000 00000000 11111111

 

  最终结果为: 00000000 00000000 00000000 11001001(0xc9)。

 

情况A:

 

  我觉得情况A的处理方式才是最正规的处理办法,但是据说linux内核使用(&0xff)。

 

   c的补码:11001001(0xc9)。

 

   c的反码:11001001(0xc9)。

 

   c的原码:11001001(0xc9)。 

 

   这里强制转换c为unsigned char型别。因此最高位的1不是正负号

 

   把c转换成Int型别   char  —–> Int

 

   Int_c的原码:00000000 00000000 00000000
11001001(把c原码的最高位1  提到最高位。其余高位补0)。

 

   Int_c的反码:00000000 00000000 00000000 11001001

 

   Int_c的补码:00000000 00000000 00000000 11001001(0xc9)。

 

   因此打印正常。

 

  以上分析,如有不正确的地方请各位指正。

 

 

其实类似的问题不是只在网络程序中才会出现的,看示例代码: 复制代码 1
#include stdio.h 2 i…

  今天在博问里面看到一个朋友的问题,大致是在网络程序中,打印出来的16进制数,莫名的出现ffffff。例如,某个byte真是值为0xc9,打印出来确是0xffffffc9。原博问连接如下:

  其实类似的问题不是只在网络程序中才会出现的,看示例代码:

  1 #include <stdio.h>
  2 int main()
  3 {
  4     char c = 0xc9;
  5     printf("A:c = %2xn",(unsigned char)c);
  6     printf("B:c = %2xn",c & 0xff);
  7     printf("C:c = %2xn",c);
  8     return 0;
  9 }

  程序输出如下:

A:c = c9
B:c = c9
C:c = ffffffc9

  可以看到:

  把c转换成unsigned
char打印是正确的。视作情况A。

  把c与
0xff做&操作后打印正确。视作情况B。

  对c不做任何处理,则问题复现了,打印出ffffffc9。视作情况C。

  情况A
B是我百度来的一些解决C现象的方法。那么我们现在来逐一分析解释ABC三种情况。

  

  首先我们必须知道,printf()函数的%x(X)输出的是Int型别的16进制格式。所以char型别的c变量会被转换成Int型别。

  其次,我们的知道计算机是用补码表示数据的。关于原码,反码,补码的知识请自行充电。

情况C:

   c的补码:11001001(0xc9)。

   c的反码:11001000(0xc9)。

   c的原码:10110111(0xc9)。 

   因为char型别是带符号的,所以最高位的1这里视为负号。

   把c转换成Int型别   char  —–>
Int

   Int_c的原码:10000000 00000000 00000000
00110111(把c原码的最高位1  提到最高位。其余高位补0)。

   Int_c的反码:11111111 11111111 11111111
11001000

   Int_c的补码:11111111 11111111 11111111
11001001(0xffffffc9)。

   所以打印出来看似诡异的值其实是合情合理的。如何避免?看AB情况。

情况B:

  我们在情况C的基础上将c与0xff做&操作。

  Int_c的补码:11111111 11111111 11111111
11001001(0xffffffc9)。

        
&

        
00000000 00000000 00000000
11111111

  最终结果为:
00000000
00000000
00000000
11001001(0xc9)。

情况A:

  我觉得情况A的处理方式才是最正规的处理办法,但是据说linux内核使用(&0xff)。

   c的补码:11001001(0xc9)。

   c的反码:11001001(0xc9)。

   c的原码:11001001(0xc9)。 

   这里强制转换c为unsigned
char型别。因此最高位的1不是正负号

   把c转换成Int型别   char  —–>
Int

   Int_c的原码:00000000 00000000 00000000
11001001(把c原码的最高位1 
提到最高位。其余高位补0)。

   Int_c的反码:00000000
00000000 00000000 11001001

   Int_c的补码:00000000
00000000 00000000 11001001(0xc9)。

   因此打印正常。

  以上分析,如有不正确的地方请各位指正。

 

相关文章