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

在这里插入图片描述

其他文章:
萌新不看会后悔的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*),函数原型为:
Check_return size_t __cdecl strlen(In_z 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.有无符号类型之间运算情况

       说完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.有无符号类型之间的转换

      下面再往深走一点,我们来说说有符合数和无符号数类型之间的转换,也就是二进制01之间的转换,说之前,我们需要先复习一下原码,反码和补码:
原码:
原码就是在最高位符号位用于表示符号,其他位表示值,比如8位一字节:

正1的原码为00000001

负1的原码为10000001

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

正1的反码为00000001

负1的反码为11111110

补码:
补码的表示方法为正数的补码就是其本身,而负数的补码就是在其原码的基础上,符号位不变,其余各位取反,最后+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 usa_1 = 10 和 int sa_1 = -100相加会得到那么大的一个数,也就是常说的最大值加1变为0的故事。

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

有无符号类型说完,我们来说说文章开头留下的问题,为什么浮点数没有有无符号之分:
想要使用unsigned,就意味着最高为要用来表示数据,而不是正负,而浮点数定义中规定内存中的数据的第一位必须是符号位,因此两者是矛盾的,至于在哪看定义,请点击下面链接自行查看:
浮点数的定义

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

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。

相关推荐


一.C语言中的static关键字 在C语言中,static可以用来修饰局部变量,全局变量以及函数。在不同的情况下static的作用不尽相同。 (1)修饰局部变量 一般情况下,对于局部变量是存放在栈区的,并且局部变量的生命周期在该语句块执行结束时便结束了。但是如果用static进行修饰的话,该变量便存
浅谈C/C++中的指针和数组(二) 前面已经讨论了指针和数组的一些区别,然而在某些情况下,指针和数组是等同的,下面讨论一下什么时候指针和数组是相同的。C语言标准对此作了说明:规则1:表达式中的数组名被编译器当做一个指向该数组第一个元素的指针; 注:下面几种情况例外 1)数组名作为sizeof的操作数
浅谈C/C++中的指针和数组(一)指针是C/C++的精华,而指针和数组又是一对欢喜冤家,很多时候我们并不能很好的区分指针和数组,对于刚毕业的计算机系的本科生很少有人能够熟练掌握指针以及数组的用法和区别。造成这种原因可能跟现在大学教学以及现在市面上流行的很多C或者C++教程有关,这些教程虽然通俗易懂,
从两个例子分析C语言的声明 在读《C专家编程》一书的第三章时,书中谈到C语言的声明问题,《C专家编程》这本书只有两百多页,却花了一章的内容去阐述这个问题,足以看出这个问题的重要性,要想透彻理解C语言的声明问题仅仅看书是远远不够的,需要平时多实践并大量阅读别人写的代码。下面借鉴《C专家编程》书中的两个
C语言文件操作解析(一)在讨论C语言文件操作之前,先了解一下与文件相关的东西。一.文本文件和二进制文件 文本文件的定义:由若干行字符构成的计算机文件,存在于计算机系统中。文本文件只能存储文件中的有效字符信息,不能存储图像、声音等信息。狭义上的二进制文件则指除开文本文件之外的文件,如图片、DOC文档。
C语言文件操作解析(三) 在前面已经讨论了文件打开操作,下面说一下文件的读写操作。文件的读写操作主要有4种,字符读写、字符串读写、块读写以及格式化读写。一.字符读写 字符读写主要使用两个函数fputc和fgetc,两个函数的原型是: int fputc(int ch,FILE *fp);若写入成功则
浅谈C语言中的位段 位段(bit-field)是以位为单位来定义结构体(或联合体)中的成员变量所占的空间。含有位段的结构体(联合体)称为位段结构。采用位段结构既能够节省空间,又方便于操作。 位段的定义格式为: type [var]:digits 其中type只能为int,unsigned int,s
C语言文件操作解析(五)之EOF解析 在C语言中,有个符号大家都应该很熟悉,那就是EOF(End of File),即文件结束符。但是很多时候对这个理解并不是很清楚,导致在写代码的时候经常出错,特别是在判断文件是否到达文件末尾时,常常出错。1.EOF是什么? 在VC中查看EOF的定义可知: #def
关于VC+ʶ.0中getline函数的一个bug 最近在调试程序时,发现getline函数在VC+ʶ.0和其他编译器上运行结果不一样,比如有如下这段程序:#include &lt;iostream&gt;#include &lt;string&gt;using namespace std;int
C/C++浮点数在内存中的存储方式 任何数据在内存中都是以二进制的形式存储的,例如一个short型数据1156,其二进制表示形式为00000100 10000100。则在Intel CPU架构的系统中,存放方式为 10000100(低地址单元) 00000100(高地址单元),因为Intel CPU
浅析C/C++中的switch/case陷阱 先看下面一段代码: 文件main.cpp#includeusing namespace std;int main(int argc, char *argv[]){ int a =0; switch(a) { case ...
浅谈C/C++中的typedef和#define 在C/C++中,我们平时写程序可能经常会用到typedef关键字和#define宏定义命令,在某些情况下使用它们会达到相同的效果,但是它们是有实质性的区别,一个是C/C++的关键字,一个是C/C++的宏定义命令,typedef用来为一个已有的数据类型
看下面一道面试题:#include&lt;stdio.h&gt;#include&lt;stdlib.h&gt;int main(void) { int a[5]={1,2,3,4,5}; int *ptr=(int *)(&amp;aʱ); printf(&quot;%d,%d&quot;,*(
联合体union 当多个数据需要共享内存或者多个数据每次只取其一时,可以利用联合体(union)。在C Programming Language 一书中对于联合体是这么描述的: 1)联合体是一个结构; 2)它的所有成员相对于基地址的偏移量都为0; 3)此结构空间要大到足够容纳最&quot;宽&quo
从一个程序的Bug解析C语言的类型转换 先看下面一段程序,这段程序摘自《C 专家编程》:#include&lt;stdio.h&gt;int array[]={23,34,12,17,204,99,16};#define TOTAL_ELEMENTS (sizeof(array)/sizeof(ar
大端和小端 嵌入式开发者应该对大端和小端很熟悉。在内存单元中数据是以字节为存储单位的,对于多字节数据,在小端模式中,低字节数据存放在低地址单元,而在大端模式中,低字节数据存放在高地址单元。比如一个定义一个short型的变量a,赋值为1,由于short型数据占2字节。在小端模式中,其存放方式为0X40
位运算和sizeof运算符 C语言中提供了一些运算符可以直接操作整数的位,称为位运算,因此位运算中的操作数都必须是整型的。位运算的效率是比较高的,而且位运算运用好的话会达到意想不到的效果。位运算主要有6种:与(&amp;),或(|),取反(~),异或(^),左移(&gt;)。1.位运算中的类型转换位
C语言文件操作解析(四)在文件操作中除了打开操作以及读写操作,还有几种比较常见的操作。下面介绍一下这些操作中涉及到的函数。一.移动位置指针的函数 rewind函数和fseek函数,这两个函数的原型是:void rewind(FILE *fp); 将位置指针移动到文件首 int fseek(FILE
结构体字节对齐 在用sizeof运算符求算某结构体所占空间时,并不是简单地将结构体中所有元素各自占的空间相加,这里涉及到内存字节对齐的问题。从理论上讲,对于任何变量的访问都可以从任何地址开始访问,但是事实上不是如此,实际上访问特定类型的变量只能在特定的地址访问,这就需要各个变量在空间上按一定的规则排
C语言文件操作解析(二)C语言中对文件进行操作必须首先打开文件,打开文件主要涉及到fopen函数。fopen函数的原型为 FILE* fopen(const char *path,const char *mode) 其中path为文件路径,mode为打开方式 1)对于文件路径,只需注意若未明确给出绝