c语言中,基本数据类型的数值范围是怎么计算出来的?

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了c语言中,基本数据类型的数值范围是怎么计算出来的?相关的知识,希望对你有一定的参考价值。

你这里对应的int是16位的,最高位是符号位,表示正负,还有15位用来表示数值,于是就有int的数据范围是-2^15~(2^15-1)
2^15就是2的15次幂,也就是15个2相乘。int类型15位数值位,每位有0,12种状态,全排列就是2^15,正负数全算上,就是其数据范围了。
参考技术A 假设int类型是8位的整形数据类型,正数是从(0000,0000)B到(0111,1111)B,
二进制1000,0000表示的是2^8,所以0111,1111则是1000,0000B-1所得,即2^8-1,这是正数的最大值,负数最高位是固定的为1,所以负数的时候从1000,0000(即为-0)到1111,1111(最高位是符号位,不参与运算)这个数,所以他的范围是-2^8
参考技术B byte\char->int
int->long
long->float
float->double
具体就是小的向大的转换,这是隐式转换。显示转换可以是大的向小的转换,不过可能会引起数据溢出,需谨慎。

C语言怎么计算数据类型范围?

之前在网上看到的一个讨论,是谁决定了数据类型的范围?

比如说,怎么确定 char 就是  -128~127 ,而不是 -127~128 呢?

说下规定

signed 的取值范围是 -(2N-1) to 2N-1 - 1

unsigned 的取值范围是 0 to (2N-1) + (2N-1 - 1)

只要记住一点就好了,就是最小值,有符号的最小值是 -128 开始,因为0占用了一个位置,所以最大值就只能是127。

无符号的最小值是 0 ,那最大值就是255了。

#怎么计算呢?

如果我们知道 #include<limits.h> 这个头文件后,可能就很容易了,因为最大值最小值都在这里面有宏定义。

#看一个老外的代码

#include <stdio.h>
#include <limits.h>
#include <float.h>

int main()
{
    printf("Range of signed char %d to %d\n", SCHAR_MIN, SCHAR_MAX);
    printf("Range of unsigned char 0 to %d\n\n", UCHAR_MAX);

    printf("Range of signed short int %d to %d\n", SHRT_MIN, SHRT_MAX);
    printf("Range of unsigned short int 0 to %d\n\n", USHRT_MAX);

    printf("Range of signed int %d to %d\n", INT_MIN, INT_MAX);
    printf("Range of unsigned int 0 to %lu\n\n", UINT_MAX);

    printf("Range of signed long int %ld to %ld\n", LONG_MIN, LONG_MAX);
    printf("Range of unsigned long int 0 to %lu\n\n", ULONG_MAX);

    // In some compilers LLONG_MIN, LLONG_MAX
    printf("Range of signed long long int %lld to %lld\n", LONG_LONG_MIN, LONG_LONG_MAX); 
    // In some compilers ULLONG_MAX
    printf("Range of unsigned long long int 0 to %llu\n\n", ULONG_LONG_MAX); 

    printf("Range of float %e to %e\n", FLT_MIN, FLT_MAX);
    printf("Range of double %e to %e\n", DBL_MIN, DBL_MAX);
    printf("Range of long double %e to %e\n", LDBL_MIN, LDBL_MAX);

    return 0;
}

#输出

Range of signed char -128 to 127
Range of unsigned char 0 to 255

Range of signed short int -32768 to 32767
Range of unsigned short int 0 to 65535

Range of signed int -2147483648 to 2147483647
Range of unsigned int 0 to 4294967295

Range of signed long int -2147483648 to 2147483647
Range of unsigned long int 0 to 4294967295

Range of signed long long int -9223372036854775808 to 9223372036854775807
Range of unsigned long long int 0 to 18446744073709551615

Range of float 1.175494e-038 to 3.402823e+038
Range of double 2.225074e-308 to 1.797693e+308
Range of long double -0.000000e+000 to -1.#QNAN0e+000

--------------------------------

#尴尬了

要是我记不住那个头文件,或者是我记不住那些宏,那要怎么搞呢?所以就有了下面的代码

#include "string.h"
#include "stdio.h"

int main()
{
 printf("Range signed char %lld to %lld\n",-(1LL << (8*sizeof(char) -1)),(1LL << (8*sizeof(char) -1)) - 1);
 printf("Range unsigned char 0 to %lld\n",(1LL << (8*sizeof(char) -1)) + (1LL << (8*sizeof(char) -1)) - 1);
 
 printf("Range signed int %lld to %lld\n",-(1LL << (8*sizeof(int) -1)),(1LL << (8*sizeof(int) -1)) - 1);
 printf("Range unsigned int 0 to %lld\n",(1LL << (8*sizeof(int) -1)) + (1LL << (8*sizeof(int) -1)) - 1);
 
 printf("Range signed long %lld to %lld\n",-(1LL << (8*sizeof(long) -1)),(1LL << (8*sizeof(long) -1)) - 1);
 printf("Range unsigned long 0 to %lld\n",(1LL << (8*sizeof(long) -1)) + (1LL << (8*sizeof(long) -1)) - 1);
 
 
 printf("Range signed long long %lld to %lld\n",-(1LL << (8*sizeof(long long) -1)),(1LL << (8*sizeof(long long) -1)) - 1);
 printf("Range unsigned long long 0 to %llu\n",(1LL << (8*sizeof(long long) -1)) + (1LL << (8*sizeof(long long) -1)) - 1);

}

#输出

Range signed char -128 to 127
Range unsigned char 0 to 255
Range signed int -2147483648 to 2147483647
Range unsigned int 0 to 4294967295
Range signed long -2147483648 to 2147483647
Range unsigned long 0 to 4294967295
Range signed long long -9223372036854775808 to 9223372036854775807
Range unsigned long long 0 to 18446744073709551615

--------------------------------
Process exited after 0.03036 seconds with return value 51

如果对上面的不是很理解的话,可以看看我这个图片

C语言怎么计算数据类型范围?

方便理解的图片

#还有一种写法

这里使用了库函数pow,但是这个函数返回值是double,这里需要特别注意一下。

#include "stdio.h"
#include "math.h"

int main()
{
 printf("signed char %ld to %ld\n",(int)-pow(2,sizeof(char)*8-1),(int)pow(2,sizeof(char)*8-1) -1);
 printf("unsigned char 0 to %ld\n",(int)pow(2,sizeof(char)*8) -1);


 printf("signed int %lld to %lld\n",(long long)-pow(2,sizeof(int)*8-1),(long long)pow(2,sizeof(int)*8-1) -1);
 printf("unsigned int 0 to %lld\n",(long long)pow(2,sizeof(int)*8) - 1);
    return 0;
}

#输出

signed char -128 to 127
unsigned char 0 to 255
signed int -2147483648 to 2147483647
unsigned int 0 to 4294967295

--------------------------------

因为pow的返回值是 double 使用的时候需要特别注意

# 说一下

数值在计算机里面都是用补码的形式存储的,补码和原码是不一样的,特别是负数。

正数的原码、反码、补码都相同。

原码: 最高位是符号位,其余为是数值位「8421定律」,最高位是0表示正数,1表示负数。

负数的反码: 在原码的基础上,符号位不变,数值位取反。

负数的补码: 在反码的基础上加 1 。



  推荐阅读:
    
    
    


嵌入式Linux
微信扫描二维码,关注我的公众号  

以上是关于c语言中,基本数据类型的数值范围是怎么计算出来的?的主要内容,如果未能解决你的问题,请参考以下文章

C语言中有符号基本整型[signed]int 取值范围(-32768——32767)是怎么算出来的?

C语言数值范围最大的数据类型(即能输出最大值)是啥?还有怎么用printf函数表示?

1、啥是数值的范围?列出的数据类型各自的范围是多少?C语言

char类型的取值范围为何是-128~127,怎么算?

c语言中长整型和整型的范围

C语言中怎么计算一个类型的取值范围?如 char 用程序算