• c/c++语言里面的带符号整数扩展


     

    先看一段代码:

    http://codepad.org/GZXrvsUE

     1 #include"stdio.h"
     2 int main()
     3 {
     4     char a=0xff;
     5     if(a==0xff)
     6     {
     7         printf("char a is 0xff
    ");
     8     }
     9     else
    10     {
    11         printf("char a is not 0xff
    ");
    12     }
    13     return 0;
    14 }

    结果输出是char a is not 0xff,很意外吧,因为a是带符号的,if比较的时候a被扩展成了四个字节的int(32位处理器下的做法)

     要是再加一句就更明了了。

    printf("int a is %x",a);
    //结果是 int a is 0xffffffff

    http://codepad.org/Q4athPaJ

    再次印证了姚新颜大哥在《c/c++深层探索》里写的那样,为了简便,K&R C中的变量只保留了整型和浮点型两种类型,其它的都是转化使用的。

    的确,char a在内存里存的是0xff不差,但在if中拿来比较的时候被当作int来比较了,而a又默认被声明为了有符号数(即使char也如此,被当作整数处理的),于是为了保证数据的正确性,就把它扩展成0xffffffff了(若用一个字节存储整数,-1表示为0xff,若用四个字节存储,-1就是0xffffffff了)。或许是这样,比较的时候,先把内存里的数拿到寄存器里处理一下,做了符号扩展,再给CPU判断。

     另外,用vs将上述代码当作c++编译结果也是如此,codepad直接提示编译通不过http://codepad.org/JXiiUo2c

    再看下一段代码

     1 //调试环境VS2008
     2 #include "stdafx.h"
     3 
     4 #include "stdio.h"
     5 int _tmain(int argc, _TCHAR* argv[])
     6 {
     7     __int8 vara=0xff;
     8     int varb;
     9     int varc;
    10     int vard;
    11     int vare;
    12     int varf;
    13     int varg;
    14     varb=(__int8)vara;
    15     varc=(int)vara;
    16     vare=*((__int8 *)&vara);
    17     varf=*((int *)&vara);
    18     varg=vara&0xff;
    19     vara=getchar();
    20     return 0;
    21 }
    View Code

    程序很简单,目的是想要将变量的值0xff送到各个比他长的变量里面去,现在为止,只用varf达到了目的

    其实将vara声明改成unsigned就能正确输出的:

    unsigned __int8 vara=0xff;

    varb=(unsigned __int8)vara;//
    varc=(int)vara;
    vare=*((unsigned __int8 *)&vara);

    虽然改成unsigned __int8 vara=0xff; 存储的内容根本没有改变。。。。但扩展时情况就不一样了

    说不清楚 建议读姚新颜大哥的《C语言标准与实现》

    又改了一下程序 测试

     1 #include "algorithm"
     2 #include "set"
     3 #include "string"
     4 #include"iostream"
     5 #include "map"
     6 using namespace std;
     7 
     8 //#include "stdafx.h"
     9 //#include "wchar.h"
    10 #define  _TCHAR char
    11 #include "stdio.h"
    12 int main(int argc, _TCHAR* argv[])
    13 {
    14     //unsigned char vara=0xff;
    15     char vara=0xff;
    16     int varb;
    17     int varc;
    18     int vard;
    19     int vare;
    20     int varf;
    21     int varg;
    22     int varh;
    23     int vari;
    24     unsigned int varj;
    25     varb=(__int8)vara;
    26     varc=(int)vara;
    27     vare=*((__int8 *)&vara);
    28     varf=*((int *)&vara);
    29     varg=vara&0xff;
    30     varh=(unsigned int)vara;
    31 
    32     vari=*(unsigned *)&vara;    
    33     varj=(unsigned int)vara;
    34     printf("vara is: %8x
    ",vara);
    35     printf("varb is: %8x
    ",varb);
    36     printf("varc is: %8x
    ",varc);
    37     printf("vard is: %8x
    ",vard);
    38     printf("vare is: %8x
    ",vare);
    39     printf("varf is: %8x
    ",varf);
    40     printf("varg is: %8x
    ",varg);
    41     printf("varh is: %8x
    ",varh);
    42     printf("vari is: %8x
    ",vari);
    43     return 0;
    44 }
    45 //--------------------------------------------------
    46 //Release下的运行结果
    47 //E:	estprocMic	ecppRelease>tecpp.exe
    48 //  vara is: ffffffff
    49 //  varb is: ffffffff
    50 //  varc is: ffffffff
    51 //  vard is: 7204b6ff
    52 //  vare is: ffffffff
    53 //  varf is: 7204b6ff
    54 //  varg is:       ff
    55 //  varh is: ffffffff
    56 //  vari is: 7204b6ff
    57 //
    58 //E:	estprocMic	ecppRelease>
    59 //  --------------------------------------------------
    60 //  Debug下的运行结果
    61 //E:	estprocMic	ecppRelease> ..debug	ecpp.exe
    62 //  vara is: ffffffff
    63 //  varb is: ffffffff
    64 //  varc is: ffffffff
    65 //  vard is: cccccccc
    66 //  vare is: ffffffff
    67 //  varf is: ccccccff
    68 //  varg is:       ff
    69 //  varh is: ffffffff
    70 //  vari is: ccccccff
    测试程序

    最后发现这种情况还是采用按位与操作比较没麻烦(var=vara&0xff;//只取最后一个字节)

  • 相关阅读:
    自实现的DNetStopWatch类
    IL Discovery 系列三 《为什么在遍历List<T>对象时同时删除其中项会抛出异常》
    高效的线程安全队列ConcurrentQueue<T>(上)
    .NET中Object.Equals()方法与Object.ReferenceEquals()方法
    麻省理工学院(MIT)的开放课程(OCW)真的不错,其音像资料
    Eclipse快捷键大全
    MyEclipse快捷键大全
    c#单文件上传下载源代码
    Tomcat 配置集锦
    asp.net(C#)多文件上传(源代码)vs2008
  • 原文地址:https://www.cnblogs.com/zhiying678/p/3160543.html
Copyright © 2020-2023  润新知