您的位置:首页 > 理论基础

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

2012-05-11 00:14 344 查看

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

整数的转换

        上一章介绍了有符号整数和无符号整合的表示方式。那么在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
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息