C语言中数据类型所占字节数与它取值范围的关系

2024-11-28 23:59:30
推荐回答(5个)
回答(1):

C语言中的数据类型,简单的可以分为整数类型和浮点数类型。所占字节数与取值范围的关系实际上是整数编码和浮点数编码的问题,整数编码的三种方式是原码、反码、补码,很容易理解,浮点数的编码格式使用的是IEEE754编码。


1、整数编码以字符类型为例。

字符类型占1个字节,共8位二进制bit位,因此排列组合数,有2^8 = 256种编码的方法。如果表示无符号字符类型,那一般来说表示【0,255】这256个数。


如果表示有符号char类型,如果表示正数,那最高位符号为0,因此可表示的最正整数是:

0-111 1111 ,转化成十进制就是127。同样的道理,符号为1表示负数。最小的负数是

1-000 0000,转化成十进制数就是-128,因此有符号char类型表示的范围是[-128,127]。


一般来说,假设整型数据类型占的二进制位数n,如果表示无符号整数则取值范围是[0,2^n-1],如果表示有符号整数,【-2^(n-1) , 2^(n-1) - 1] 。


2、浮点数类型

浮点数编码一般采用的是IEEE754的编码规则,这个编码格式主要指出了浮点数有效数字、指数以及符号位所占的二进制位数。简单概括为:


格式       长度  符号位 指数位  尾数位  有效位数  指数偏移   尾数说明

单精度     32     1       8       23      24        127       有一位隐含位

双精度     64     1      11       52      53       1023       有一位隐含位

扩展双精度 80     1      15       64      64      16383       没有隐含位

注意:扩展双精度格式没有隐含位,因此它的有效位数与尾数位数一致,而单精度和双精度格式均有一位隐含位,因此它们的有效位数比尾数位数多1。


一般很少自己手动来算浮点数的取值范围,可以使用如下程序来计算。

#include 
typedef struct FP_SINGLE
{
unsigned __int32 fraction : 23;
unsigned __int32 exp      : 8;
unsigned __int32 sign     : 1;
} fp_single;
typedef struct FP_DOUBLE
{
unsigned __int64 fraction : 52;
unsigned __int64 exp      : 11;
unsigned __int64 sign     : 1;
} fp_double;
typedef struct FP_EX_DOUBLE
{
unsigned __int64 fraction;
unsigned __int32 exp  : 15;
unsigned __int32 sign : 1;
} fp_ex_double;
int main()
{
float x;
fp_single * fp_s = (fp_single *)&x;
fp_s->sign = 0;
fp_s->exp = 0xfe;
fp_s->fraction = 0x7fffff;
printf ("float 最大数:      %le\n",(double)x);
fp_s->sign = 0;
fp_s->exp = 0x1;
fp_s->fraction = 0x0;
printf ("float 最小数:      %le\n",(double)x);
fp_s->sign = 0;
fp_s->exp = 0;
fp_s->fraction = 0x1;
printf ("float 最小弱规范数:%le\n\n",(double)x);
double y;
fp_double * fp_d = (fp_double *)&y;
fp_d->sign = 0;
fp_d->exp = 0x7fe;
fp_d->fraction = 0xfffffffffffff;
printf ("double 最大数:      %le\n", y);
fp_d->sign = 0;
fp_d->exp = 0x1;
fp_d->fraction = 0x0;
printf ("double 最小数:      %le\n", y);
fp_d->sign = 0;
fp_d->exp = 0;
fp_d->fraction = 0x1;
printf ("double 最小弱规范数:%le\n\n", y);
char ch[10];
fp_ex_double * fp_ex_d = (fp_ex_double *)ch;
fp_ex_d->sign = 0;
fp_ex_d->exp = 0x7ffe;
fp_ex_d->fraction = 0xffffffffffffffff;  
// 不知道扩展双精度浮点数如何输出,
// 不过可以用od跟踪,然后找到ch[0]的地址,在数据窗口中选择 浮点 80为长双精度,
// 就可以看到数值了。
fp_ex_d->sign = 0;
fp_ex_d->exp = 0x1;
fp_ex_d->fraction = 0x8000000000000000;      
fp_ex_d->sign = 0;
fp_ex_d->exp = 0;
fp_ex_d->fraction = 0x1;      
return 0;
}

回答(2):

对于一个两个字节的整数,它在内存中占的空间是16位,可以表示2^16=65536种不同的值,如果我们不考虑符号的话,只把他们当成二进制的数,那么恰为0~65535间的所有整数。而我们还要表示负数,一般用补码完成一个0~65535间的非负整数到一个有符号整数的映射的,说白了就是同余,比如-1=65535(mod 65536),所以65535的二进制表示1111111111111111就表示-1。用补码是很方便的,因为同余的关系嘛,加减乘除都不需要转化,直接计算就可以了。还有一些不太方便的编码,比如原码,反码,参见相关书籍。
顺便说一下,现在好多编译器里的int都是32位的,即int和long int是一样的。

回答(3):

每个字节8位,2个字节16位
若是有符号的int,那么除去一个符号位,还有15位,
所以取值范围是
非负数:2^15-1 到 0
负数:-1 到 - 2^15
所以int的取值范围是 -32768到32767

如果是无符号的int,那么取值范围是2^16-1 到0
就是 0到65535

回答(4):

补充一点,在32位环境中(如VC),int占4个字节,另外,计算机表示整型数据是补码表示.你把补码弄明白了这个问题就不难搞明白了。

回答(5):

int 占2个字节,16伪
2的16次方