整形数,浮点数

来源:互联网 发布:梦幻西游账号数据 编辑:程序博客网 时间:2024/04/28 14:56

一说到数字,我们脑子里就会闪现出一些数字的类型,比如,int,double,float,long,当然还有一些复合类型,比如

指针类型,枚举类型,结构体类型等等。关于这些类型的变量在内存中所占的字节数到底是多少,下边我来给出测试:

windows系统vs编译器下:

#define _CRT_SECURE_NO_WARNINGS 1#include<stdio.h>#include<stdbool.h>int main(){printf("%d\n",sizeof(char));printf("%d\n", sizeof(short));printf("%d\n", sizeof(int));printf("%d\n", sizeof(long));printf("%d\n", sizeof(long long));printf("%d\n", sizeof(float));printf("%d\n", sizeof(double));printf("%d\n", sizeof(long double));printf("%d\n", sizeof(bool));system("pause");return 0;}
运行结果如下

或许,你到现在还以为c语言里没有bool类型,其实,c99已经引入了,只是使用的时候你需要加头文件而已。

同样的代码,拿到linux的gcc下试试,看看运行结果吧。


只有long double的大小不同,其他的应该都一样。要是在g++下还会有不同,你可以试试。


指针类型的大小,32位系统下都是4.结构体的大小,前边那篇文章中已经有讲过。

(一)整形数

1.整形数的类型有:int,signed int,unsigned int(size_t),short,long,long long等等。

2.整形提升:

   c语言中的数据类型转换分成两种 ,一种是隐式类型转换,一种是显式类型转换(强制类型转换)。强制类型转换

我们见的比较多了(比如动态内存分配函数里....),这里就只给出隐式类型转换。

当不同的数据类型的数进行计算时,就会发生隐式类型转化,隐式类型转换的步骤:(1)表达式中的char,short都

变成int,float变成double。(2)根据参与计算的数据类型从低精度向高精度转换。

精度低到高:char,short -> int -> unsigned int -> long ->double 

                 float->double

下边给出几个实例:

实例1:

int a = INT_MAX;int b = 2;long long c = a + b;long long c = (long long)(a + b);long long c = (long long)a + b;

分析上边的表达式。

long long c = a + b;//发生溢出。首先计算的是a+b,都是int,已经发生溢出,再转换,当然是没用啦~~
long long c = (long long)(a + b);//原因类似上边,已经发生了溢出,才进行 转换。
long long c = (long long)a + b;//正确,b被隐含转换成long long

实例2:下边代码的运行结果是什么??

int main(){unsigned char a = 200;unsigned char b = 100;unsigned char c = 0;c = a + b;printf("%d %d",a+b,c);system("pause");return 0;}

怎么感觉输出结果是300 300呢??其实并不是。我来分析一下。由于a和b都是无符号 char型,进行运算都会发生整

形提升。都被提升为int。所以执行c = a + b时,

a被提升为:00000000 00000000 00000000 11001000

b被提升为:00000000 00000000 00000000 01100100

a+b:          00000000 00000000 00000001 00101100

由于c是一个字节,所以a+b会被截断,变成00101100,即10进制的44

而直接输出a+b的值时,32个比特位,结果是300.

实例3:

int main(){char c;unsigned char uc;unsigned short us;c = 128;uc = 128;us = c + uc;printf("0x%x ",us);us = (unsigned char)c + uc;printf("0x%x ", us);us = c + (char)uc;printf("0x%x ", us);system("pause");return 0;}

这道题看起来好像比较头疼。不过,没关系,干程序员这一行,需要的是细心,耐心,哈哈大笑

c = 128.由于它是有符号数,所以8个比特位中1位是符号位,7位是实际的数.128就是10000000。然而,它的第一位

表示符号。进行整形提升时,被提升为 11111111 11111111 11111111 10000000.

uc = 128.由于它是无符号数,所有的比特位都表示实际数字。128是10000000,进行整形提升时,被提升为:

00000000 00000000 00000000 10000000

两个进行相加,取后边的16个比特位,结果是0,也是16进制的0.

当c被强制转化成无符号整形时,128的二进制中的首位1并不表示符号,进行整形提升时,被提升为:

00000000 00000000 00000000 10000000

再与uc相加,1取低位的16个比特位,结果是256,即就是16进制0x100

当uc被强制转化成有符号char时,128的二进制中的首位1表示符号,进行整形提升时,被提升为:

11111111 11111111 11111111 10000000

与c相加之后,取低位的16个比特位,结果是0xff00.

所以程序的输出结果是:0x0 0x100 0xff00

3.上边代码出现了INT_MAX,下边就此问题展开说明。

   在《c语言点滴》(赵岩著)这本书中3.10节关于整形数和浮点数给出一个口诀:296两宏两头。29表示整形数的上

限是2*10^9,6表示浮点数的有效位是6位,两宏指的是_MAX类型宏 和EFLT_PSILON类型宏 ,两头指的是float.h和

limits.h。

关于这两个头文件:

float.h中主要给出浮点数,double数的最小值,最大值,等等。下边给出部分。

limits.h中给出整形数的范围,可以自行查看。

下边给出整形数这块的重点例题:

例1:

unsigned  char c = -1;printf("%u",c);
%u是无符号整形的形式。unsigned c = -1,在计算机中以补码形式存储,即为1111 1111,计算机会认为它是一个正

数当它变成无符号整形时,前边补24个0,最终就是255.

无符号char是一个字节(32位系统)。

例2:

char c = -128;printf("%u",c);

最终的结果是,c = 11111111 11111111 11111111 10000000

-128:原码;1 1000 0000反码:1 0111 1111 补码:1 1000 0000

计算机会认为c是一个有符号的字符型,变成无符号数整形时,前边补24个1.

总结:如果是无符号数,小范围->大范围:前边补0

           如果是有符号数,小范围->大范围,前边补符号位。

例3:

int i = -20;unsigned int j = 10;printf("%d",i + j);
程序的运行结果是-10,请看分析过程:

-20原码:10000000 00000000 00000000 00010100

     反码:11111111 11111111 11111111 11101011

     补码:11111111 11111111 11111111 11101100

10原码:00000000 00000000 00000000 00001010

    反码:01111111 11111111 11111111 11110101

    补码:01111111 11111111 11111111 11110110

两个补码相加之后转换成原码:10000000 00000000 00000000 00001010   就是-10

例4:

char a[1000];int i = 0;for(i = 0;i < 1000;i++){    a[i] = -1 - i;}printf("%d",strlen(a));

看看上边这段代码执行后的结果是什么。strlen可以求字符数组的长度,找\0,找到为止。


所以,i = 0时,a[0] = -1,a[i]就是-1,-2,......,-128,下来就是127,....,1,0(相当于是上边的椭圆逆时针转一

圈,0就是结尾符了,\0的ascii是0)。所以,strlen (a) = 128+127 = 255.

(二)浮点数

在IEEE754标准中,给出了V = (-1)^s*M*2^E(1<=M<2)

   s代表符号,M是尾数,E是阶码。E = e+偏移位。

32位浮点数和64位浮点数的标准格式,如下图 :


知道这些之后,我们就应该推导一下浮点数的表示范围。下图以32位浮点数为例(64位的可以自己整理)


下边看一道例题:

int num = 9;float *pfloat = (float *)#printf("%d ",num);printf("%f ",*pfloat);*pfloat = 9.0;printf("%d ",num);printf("%f ",*pfloat);
分析:第一个printf输出9毫无疑问。
           第二个printf,pfloat是指向浮点数的指针。所以系统便认为9(0 00000000 00000000000000000001001)是

            一个浮点数。阶码E = 0,所以该数是无限接近于0的数,所以输出0.

         第三个printf,*pfloat在内存中表示为:0 10000010  00100000000000000000000,若以%d输出,就是一个比

          较大的数。即就是01000001000100000000000000000000表示的整形。

        第四个printf,输出9.0。也没什么问题。


关于数字,就整理这么多,如果有不合理的地方,希望指出~吐舌头

1 0