《深入理解计算机系统》笔记一:信息的表示与处理(3)——整数的转换、扩展、截断和运算

整数的转换、扩展、截断和运算

整数的转换

        上一章介绍了有符号整数和无符号整合的表示方式。那么在C语言中,一个整数常量的大小和符号是什么呢?请看如下定义

#define A 123
#define B 128

        A和B是两个宏,经过预处理,A和B会被替换为两个整数。那么编译器是如何存储这两个整数的呢?也就是说A和B有没有符号?在栈/静态存储区中占几个字节呢?
        默认的,常量被定义为有符号的,而大小则由所能容纳此整数的最小类型来定义(《C和指针》3.1基本数据类型)。以上两个定义,A和B都是有符号的,char的表示范围为0-127,short的范围为0-32767,所以,A被当作一个有符号的char存放,B超过了有符号char所能表示的最大值,所以被当作为有符号short存放。但实际情况是否如此呢?

    #define A 123
    #define B 140

    printf("A size = %d\r\n", sizeof(A) );
    printf("B size = %d\r\n", sizeof(B) );

        A size = 4
        B size = 4

        我的环境是UBUNTU 2.6.35内核,X86,gcc4.4.5,可见在此环境中,无论整数常量被定义为多大,存储都是四个字节。具体要根据实际的反汇编代码来判断,这个等下一章时会进行验证。

        如果想规定常量的符号和大小,需要在后面加上U(u)和L(l)来限定。123U,则表示为无符号的char;123UL,则会表示为无符号的long(如果默认储存为int,那么L就没有用了?)

        如果一种类型的变量被赋给另外一种类型的变量时,会发生隐式转换

    int x = -1;
    unsigned int u = 2147483648;

    show_bits( (unsigned char *)&x, sizeof(x), "x bits:" );
    show_bits( (unsigned char *)&u, sizeof(u), "u bits:" );

    printf("x = %u, %d\r\n", x, x );
    printf("u = %u, %d\r\n", u, u );


结果:
x bits:
11111111 11111111 11111111 11111111 
u bits:
00000000 00000000 00000000 10000000 
由于机器是小端的,所以上面U的正常比特位应该是
10000000 00000000 00000000 00000000

x = 4294967295, -1
u = 2147483648, -2147483648
        可以看出,同样一个整数,当作正数和当作负数的结果,是不一样的。

        如果一个表达式中运算数的符号不同,那么编译器会把有符号变量强制转换为无符号类型,所以,当使用“<和>”判断时,要格外注意。最好的方法,是用X - Y与0相比,看下面几个使用<和>的例子:

    #define A   -1
    #define B   0

    if( A < B )
    {
        printf("expression is True\r\n");
    }
    else
    {
        printf("expression is False\r\n");
    }

结果:expression is True。编译器认为A和B都是有符号的,-1 < 0

    #define A   -1
    #define B   0U

    if( A < B )
    {
        printf("expression is True\r\n");
    }
    else
    {
        printf("expression is False\r\n");
    }

结果:expression is False。编译器将A都转换为无符号数,0xFFFFFFFF显然比0大

    #define A   2147483647
    #define B   (int)2147483648U

    printf("A = %.8x, B = %.8x\r\n", A, B );

    if( A > B )
    {
        printf("expression is True\r\n");
    }
    else
    {
        printf("expression is False\r\n");
    }

结果:
A = 7fffffff, B = 80000000
expression is True。用(int)将B转换为有符号数,此时B被看作为负数

整数的扩展与截取


较小类型的数据扩展为较大类型时,如果是无符号整数,则前头填充0,称为零扩展(zero extension);如果是有符号的,前头按符号为填充,称为符号扩展(sign extension)

    short sx = -12345;
    unsigned usx = 53191;

    int x = sx;
    unsigned ux = usx;

    printf("x = %.8x\r\n", x );
    printf("ux = %.8x\r\n", ux );

结果:
x = ffffcfc7
ux = 0000cfc7


你可能感兴趣的:(汇编,ubuntu,存储,扩展,extension,编译器)