写点什么

萌新不看会后悔的 C++ 基本类型总结(一)

用户头像
花狗Fdog
关注
发布于: 2021 年 03 月 05 日




其他文章:

萌新不看会后悔的C++基本类型总结(二)

萌新学习C++容易漏掉的知识点,看看你中招了没有(一)

萌新学习C++容易漏掉的知识点看看你中招了没有(二)

C/C++什么时候使用二级指针,你知道吗?

C++类型转换几种情况

C++使用指针,动态数组,指针做参数需要注意的问题等总结



       c++的基本类型包括 char,short,int,long,lang lang(C++新增的),double,float,bool,其中除了 double,folat 两种浮点数类型之外都有有符号和无符号两种类型,也就是说一共 12 种基本类型,至于为什么浮点数没有无符号类型,后面会说。


0.浮点数

浮点数包括 float,和 double,还有 long double,这些书上面都有解释,我们不再赘述,只挑重点讲一讲:


单精度 float 和双精度 double 浮点数,那么单精度和双精度有什么区别?

就是前者占 4 字节,后者占 8 字节,前者有效数字位数位 8 位,后者为 16 位,还有就是取值范围不同。

等等,这显然不是我们想要的答案,比如说我给你举个例子:


 float number_1 = 123456789.123456789; float number_2 = 123456789.123456789f; double number_3 = 123456789.123456789;
复制代码

运行结果:

通过这个你能告诉我你就理解单精度和双精度了吗?我相信很多人还是只知道有单精度和双精度这个叫法,却不知道具体意义。


想要知道具体,我们需要查阅 IEEE754 标准,该标准定义了 float 和 double,float 有 32 位,double 有 64 位,不管是 32 位还是 64 位,它们都由符号位,指数位,和尾数位构成:


| 种类 |符号位 | 指数位 |尾数位 |

|--|--|--|--|

| float | 第 31 位(占 1bit) | 第 30~23 位(占 8bit)| 第 20~0 位(占 23bit) |

| double| 第 63 位(占 1bit) |第 62~52 位(占 11bit) | 第 51~0 位(占 52bit) |


取值范围看指数部分,float 指数部分占 8 位,也就是 0 ~ 255,由于有正负,所以为-128 ~ 127, 标准规定 float 偏移量为 127,也就是-1-127~255-127 为-128 到 128。

取值范围有-2 ^128 到 2 ^128,是不是够大?也就是约等于你们熟悉的-3.4E38 到+3.4E38。


精度范围看尾数部分,23 位所能表示最大的数是 2 ^23-1=8388607,也就是说尾数值超过这个值后 float 将无法精确表示,所以 float 最多能表示小于 8388607 的小数点后 8 位,但绝对能保证为 7 位,这也是 float 精度位 7 ~ 8 位的原因。


同理,double 类型的指数位为 11 位,取值范围有-2 ^10232 到 2 ^10232,既为你们熟悉的-1.7E+308~1.7E+308。

精度范围为 2^52-1=4503599627370495,为 16 位。所以精度最高位 16 位,一定可以保证 15 位,这也 double 精度位 15 ~ 16 位的原因。


也是单精度 8 和双精度 16 的由来。


1.各种类型占用内存大小问题

下面先来看一段代码。

 

 char c = 'a'; short s = 1; int i = 1; long l = 1; long long ll = 1; double d = 1.0; float f = 2.5f; bool b = 0;// 在你的机器上面占用多少字节,具体可以使用sizeof运算符得到: std::cout << sizeof(c); std::cout << sizeof(s); std::cout << sizeof(i); std::cout << sizeof(l); std::cout << sizeof(ll); std::cout << sizeof(d); std::cout << sizeof(f); std::cout << sizeof(b); //运行结果为1,2,4,4,8,8,4,1
复制代码

与所有人一样,一上来我们先了解各个类型占据内存的大小。

>这里有一个误区:在不同的编译器,每个类型占用的内存可能是不同的,这和编译器有关,一个类型占用多少字节由编译器在编译期间决定,并不和系统是否是32位和64位有关,不要以为在16位机器上就是16位,在36位机器上就是32位。


可以查看<limits.h> 头文件,int 和其他类型的大小是由<limits.h> 中的宏定义来决定的:


INT_MAX//随便写一个定义的常量,鼠标右击转到声明可以跳到limits.h头文件查看,如下:
复制代码


所以我这里就不再列出烂大街的最大值,最小值。

我只是告诉你,这个值应该怎么得到。要知其然,还要知其所以然。

比如我们知道 char 的字节为 1,一字节 8 位可以有 256 种组合,所以 int 的字节为 4 也就是 256*256 等于 65536,这种东西我们理解就好了,没必要背这个最大值,最小值,只需要如何得到就好了。



2.sizeof 和 strlen 的区别


>然后说一下sizeof和strlen的区别,可能有很多萌新记不住这两个的区别:

>

>>sizeof() 是运算符,它不是函数,不要因为它长的像函数,就上它的当,sizeof 其值在编译时就已经计算好了,参数可以是数>组,指针,对象,函数等等,它的功能就是获取数组,指针等类型的字节大小。

>数组——编译时分配的数组空间大小

>指针——存储该指针所用的空间大小

>类型——该类型所占空间大小

>对象——对象的实际所占空间大小

>函数——函数的返回类型所占的空间大小,这里的返回类型自然也不能 void

>

>>strlen()是函数,要运行时才能计算,参数必须字符型指针(char*),函数原型为:

Checkreturn sizet __cdecl strlen(_Inz const char * _Str);

该函数的功能是返回字符串的长度,该字符串可能是自己定义的,也可能是内存中随机存储的,该函数实际完成的功能是从代>表该字符串的第一个地址开始遍历,知道遇到结束符 NULL,返回的长度不包括 NULL。


 char * ch = "nihao"; std::cout << strlen(ch); // 结果为5
复制代码

3.整形字面值

与 C 相同,C++也有三种不同的书写方式来书写整数。

1.使用前一位或者两位来标识数字常量的基数,如果第一位是 1 ~ 9 则表示基数为 10,也是十进制写法。

2.如果第一位是 0,第二位是 1 ~ 7,则基数为 8,也就是八进制。

3.如果前两位为 0x 或者 0X 则表示基数为 16,相当于十六进制。


 int number_1 = 66; int number_2 = 066; int number_3 = 0x66; std::cout << number_1 << std::endl; std::cout << number_2 << std::endl; std::cout << number_3 << std::endl;
复制代码

运行结果:

为什么要有这几种书写方式呢,在有些地方是使用八进制或者是十六进制表示,我们可以直接使用该表示方法赋值给 number,而不必转换为十进制,总而言之,就是为了方便,为了偷懒,反过来,输入识别进制是有了,反过来,C++也提供了不同进制的输出方式,但 C++默认是十进制的输出方式,想要改变默认的十进制输出方式,需要用到 cout 的一些特殊特性,头文件 iostream 提供了 dec,hex,oct,分别用于表示十进制,十六进制和八进制:


 int number_1 = 66; int number_2 = 066; int number_3 = 0x66; std::cout << std::dec; std::cout << number_1 << std::endl; std::cout << std::oct; std::cout << number_2 << std::endl; std::cout << std::hex; std::cout << number_3 << std::endl;
复制代码

运行结果:


>需要注意的是在修改之前,之前修改的格式会一直生效。




4.有无符号类型之间运算情况


&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;说完 sizeof 和 strlen,继续说基本类型的长度,计算机内存的基本单位是位(bit),8 位为一个字节,每一位有 0 和 1 两种组合,也就是说一个字节有 ==*2 2 * 2 * 2 2 2 * 2 * 2 2 = 256*== 种组合。上面使用 sizeof 得到 char 的字节为 2 字节,也就是说,char 类型可以表示 0~ 255 或者 -128 ~ 127 ,上面说过,除了浮点数没有有无符合之分,剩下的类型都有有符合和无符号之分,也就是 char 支持 0~255,也可以支持-128 ~ 127,至于我们需要有符合还是无符号的,决定于我们的应用场景。


>执行运算时,如果一个运算数是有符号的,而另一个是无符号的,那么C/C++会隐式的将有符号参数强制转换为无符号类型,并假设这两个数都是非负数。

>当两种类型进行混合运算时,运算结果为正数时,结果不会出现异常,当运算结果为负数时就会出现异常结果,而且异常的结果往往很大。


 unsigned int usa_1 = 10; int sa_1 = -100; unsigned int usa_2 = 10; int sa_2 = -5; std::cout <<usa_1+sa_1; std::cout << usa_2 + sa_2;
复制代码

运行结果:



5.有无符号类型之间的转换

&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;下面再往深走一点,我们来说说有符合数和无符号数类型之间的转换,也就是二进制 01 之间的转换,说之前,我们需要先复习一下原码,反码和补码:

<font color=#6699ff size=3 face="STCAIYUN">原码:</font>

原码就是在最高位符号位用于表示符号,其他位表示值,比如 8 位一字节:


>正 1 的原码为 00000001


>负 1 的原码为 10000001


<font color=#cc0000 size=3 face="STCAIYUN">反码:</font>

反码的表示方法为正数的反码时其本身,而负数的反码是在其原码的基础上,符号位不变,其余各数取反:


>正 1 的反码为 00000001


>负 1 的反码为 11111110


<font color=#009933 size=3 face="STCAIYUN">补码:</font>

补码的表示方法为正数的补码就是其本身,而负数的补码就是在其原码的基础上,符号位不变,其余各位取反,最后+1,也就是在反码的基础上+1:


>正 1 的补码 000000001


>负 1 的补码 111111111


复习了原码反码补码后,我们说:


1.无符号数,不存在正负之分,所有位都用来表示数的本身。

2.有符号数,最高为用来表示数的正负,最高位为 1 则表示负数,为 0 则表示为正数。


无符号数想要转换为有符号数需要三步:

1.看无符号数的最高为是否为 1。

2.如果不为 1,则有符号数就直接等于无符号数。

3.如果无符号数的最高位为 1,则将无符号数取补码,得到的数就是有符号数。


举个例子:

>无符号数 10 转换为有符号数

无符号数 10 的二进制写法:0000 1010

根据三步法得到:

有符号数 10 的二进制写法:0000 1010

还是 10


>无符号数 129 转换为有符号数

无符号数 129 的二进制写法:1000 0001

根据三步法得到:

反码:1111 1110

补码:1111 1111

也就是说转换成有符号后,代表的是-127


同样,有符号数想要转换为无符号数,同样需要这三步:

1.看有符号数的最高位是否为 1,

2.如果不为 1(为 0),则无符号数就直接等于有符号数;

3.如果有符号数的最高位为 1,则将有符号数取补码,得到的数就是无符号数。


举个例子:

>有符号数-7 转换为无符号数

有符号数-7 的二进制写法:1000 0111

根据三步法得:

反码:1111 1000

补码:1111 1001

也就是无符号数 249

总而言之就是看符号位,如果是 1,就把它当作负数来处理反码,补码。



6.为什么会出现结果数值异常大


还记得上面有一句话是这样说的==当运算结果为负数时就会出现异常结果,而且异常的结果往往很大==。现在,我们来处理这个问题:

我们可以把变量的取值范围当作是汽车的里程表,一来为了好理解,而来确实是这样的,拿 char 来说:

这也就解释了为什么 unsigned int usa1 = 10 和 int sa1 = -100 相加会得到那么大的一个数,也就是常说的最大值加 1 变为 0 的故事。


7.为什么浮点数没有分有无符号类型

有无符号类型说完,我们来说说文章开头留下的问题,为什么浮点数没有有无符号之分:

想要使用 unsigned,就意味着最高为要用来表示数据,而不是正负,而浮点数定义中规定内存中的数据的第一位必须是符号位,因此两者是矛盾的,至于在哪看定义,请点击下面链接自行查看:

浮点数的定义


还有就是在某些编译器下,会将定义的 unsigned folat 和 unsigned double 自动转换为 unsigned int 类型,而不报错,这时使用 sizeof 来测量的话得出来的是 int 的大小,也就是 4.





发布于: 2021 年 03 月 05 日阅读数: 14
用户头像

花狗Fdog

关注

还未添加个人签名 2021.02.06 加入

还未添加个人简介

评论

发布
暂无评论
萌新不看会后悔的C++基本类型总结(一)