写在前面:整理完Git相关内容后,对C++的处理数据方面的相关知识进行了整理,本文仅整理了基本数据类型,后续会进行补充。文中有不足之处,还望交流指正
目录
数据处理
二、C++中的基本数据类型及其特性
1)概述
在介绍整型前,先了解C++中内置的整型和C++ 11中新增的整型类型
C++内置的整型:char、short、int、long、bool、unsigned short、unsigned int、unsigned long、unsigned char
C++ 11 新增的整型:unsigned long long 和 long long
其中char、short、int、long的排序跟为其分配的内存空间大小相关,char分配1字节,而short 至少分配2字节(即16位),int 至少4字节, long 至少8字节,此处的至少跟工程上应用有关,也体现出了C++的智能特性,会根据变量的大小为其分配合适的内存空间,但在具体使用时,应选取合适的类来定义变量,以达到节省内存空间的目的。毕竟,能省一点是一点
在介绍具体的类及用法之前,先对C++命名规范作初步介绍:
1.名称中只能使用数字、字母字符、下划线
2.名称的第一个字符不能是数字
3.区分大小写字符
4.不能将关键字用作名称
5.双下划线和单下划线开头的名称不建议使用,使用单下划线的名称用作变量名时,用作全局标识符
对上面的第二条作了加粗显示,在日常编写代码时可能不会注意,其它几条都比较常规,不过多赘述
2) int、unsigned int
鉴于C++对大小写敏感,在创建整型变量的时候,使用小写int,而不是INT,否则会造成编译报错
int example=0 //valid
INT newexample=0 //invalid
观察上方代码行也会发现,INT并未识别为类,故也无法为我们创建整型的变量
当我们用int 创建变量时,以上方example为例,进行的操作是通过读取int ,内存分配了至少16位的内存空间用于存储数据的值,并将此空间标识为 example ,读取空间时即会读取空间内的值,也就是0,而这个空间在哪,开发人员并不知晓。若要知道空间的地址,可通过&运算符来进行检索
由于int至少16位的特性,可以知道16位的int表示的范围在-32768~+32767,在头文件limits中有明确规定计算机中各个整型变量的最大值与最小值,可通过如下代码查看:
#include <iostream>
#include <climits>
int main()
{
using namespace std;
int intmax=INT_MAX;
int intmin=INT_MIN;
cout<<"int max is "<<intmax<<endl;
cout<<"int min is "<<intmin<<endl;
return 0;
}
其中INT_MAX、INT_MIN是limits头文件中的定义,通过define定义将程序中所有的INT_MAX、INT_MIN赋值,这是一种定义字符常量的方法,通过引入limits头文件我们可以输出相应的类的最大值与最小值,从而知晓它们的范围
通过sizeof语句我们能知晓相应的类或变量所占用的字节大小,如下:
cout<<"int is "<<sizeof(int)<<endl;
cout<<"intmax is "<<sizeof intmax<<endl;
在对类使用sizeof时,需添加圆括号,而对变量使用时,括号可以省略
了解了int类表示的整型范围,接下来介绍int类在C++中创建变量时的语法:
int example = 0;
int example{0};
int example={};
int example{};
如上的几种定义方式都可用于变量的初始化,须注意的是第二行和第四行的定义方式,C++中支持通过{}j进行单值变量的赋值,花括号中内容为空,则默认赋值0,等号可使用也可以不使用
也可以直接声明变量,例如下列:
int example;
这种做法可能造成隐患,因为未对变量采取初始化,若后续未给变量赋值,该变量的值将是不确定的,即是该内存单元的原始值
无符号数并不陌生,它表示的是非负数,适用于变量值恒非负的场景,相比于int的范围-32768~+32767,无符号数unsigned表示的范围更广,为0~65535,这意味着在非负的场景下,它往往比int更好用
C++中具有如下特性,若对int赋值为INT_MAX,对unsigned int赋值为UINT_MAX,并给他们的值加1,并不会造成错误。相反,会获取另一端的值,例如int将从+32767变为-32768,unsigned int 将从65535 变为 0 ,同理 在他们的最小值时执行减1操作,会得到它们的最大值,这一特性保证了编译时的稳定性,但若在平时的编程中不注意,可能造成意料之外的错误
在计算机中,数据都是以二进制存储的,但在输出时,默认采用十进制进行内容的输出,整型变量是存在整型字面值的,除了上述的两种进制,计算机中还有八进制(老式UNIX版本)和十六进制(多用来表示地址),下面将介绍C++中这些进制的表示法:
int example=64; //十进制
int example=0x64; //十六进制
int example=064; //八进制
如上,前缀有0x或0X的计算机将识别为十六进制,第一位有0,第二位为0~7的数据,计算机将识别为八进制,尽管这些数据在计算机中都是通过二进制进行存储的
这时,如果对上述数据进行输出,得到的结果都会以十进制进行表示,这是为什么?
原因是cout的智能化输出,在默认情况下,cout会以十进制输出内容,而不会管内容在程序中是如何书写的,如果要输出对应进制的文件,则需先声明cout的输出方式,如下:
int example=64; //十进制
cout<<hex;
int example=0x64; //十六进制
cout<<oct;
int example=064; //八进制
上述的声明切换了cout的默认输出方式,从而能输出对应进制的内容
这类声明语句并不会在屏幕上显示任何内容,仅仅是改变cout显示整数的方式
需注意的是像上述的hex和oct是位于名称空间std中的,若未使用using namespace std语句,则需通过std::hex、std::oct来使用,若声明了名称空间后,在创建变量名时则不能使用int hex这种形式,以免报错
3) C++如何确定变量的类型
在C++中,若用常量表示一个数字,除非有存储为其它类型的理由,否则C++会默认用int来进行存储,如下:
cout<<"I have "<<3<<" apples"<<endl;
在识别数字3时,C++首先会检索它是否具有后缀,整数后面的l或者L表示long常量,u或U表示unsigned int常量,ul(任何顺序大小写均可)表示unsigned long 常量,在C++ 11中,ULL(大小写均可)用来表示unsigned long long常量,若识别到相应的后缀,则会按相应的类型进行存储
凡事也有例外,例如有时并未添加后缀,例如数字若是32768,则int存不下,会识别后存为long类型,若数据量更大,则会用long long类型进行存储,这是C++的一大特性
在表示地址时,同样是大数,但会存储为unsigned int而不是long类型,这是因为表示地址时,内存地址是没有符号的,因此unsigned int比long更合适
4)char
C++中的char类型被划分到了整型,这是因为它是专为存储字符(如字母和数字)设计的,对于计算机中的字符而言,它足够长——能表示计算机中的所有基本符号,所以通常为它分配一个字节大小的内存空间,又因为变成语言通过使用字母的数值编码解决了存储字母的问题,所以char相当于是另一种形式的整型
像我们熟知的ASCII编码,是在美国最常用的字符集,C++支持的宽字符类型使C++能存储更多的值,如国际Unicode字符集中的值
此处对ASCII编码进行补充:'A'在ASCII中的编码为65,所以我们若进行如下操作:
char example='A';
int output=example;
cout<<"output is "<<output<<endl;
输出将是65,这是因为char存储的其实不是字符'A',而是对应的字符编码65,所以output获取的是对应字符编码的值,输出自然就是65
同样的,若执行如下代码,同时输入字符A:
char example;
cin>>example;
cout<<"example is "<<example<<endl;
则输出也是字符A,看起来很合理,但实际涉及到了cin和cout的智能转化,example通过cin存入的是字符A的字符编码的值,即65,但在输出时,通过cout检测到example的类型为char,所以cout将字符编码转化为了对应的字符A进行输出,这种字符与字符编码值得转化使C++在处理字符类问题时更加的容易
5)成员函数cout.put()
类表示了如何表示和控制数据,成员函数归类所有,描述了操纵类数据的方法;只能通过类的特定对象来使用成员函数,通过对象使用成员函数时,必须通过句点将对象和成员函数连接起来,此处的 . 也被称为成员运算符。所以标题cout.put()的意思也就易于理解了——通过类对象cout来使用成员函数put()
cout.put()提供了另一种显示字符的方法,可以替代<<
这是C++ Release 2.0 之前的一种显示方法
6)转义序列
有些字符不能通过键盘直接输入到程序中,例如回车无法使字符串中包含一个换行符,这时就需要用到转义序列,转义序列可在字符串和字符常量中进行使用,方便我们进行一些额外的操作,此处列举常用的几种转义序列:
\n 换行符 ——实现字符串文本的换行
\a 振铃 ——执行时使终端扬声器振铃
\" 文本内容\" ——将双引号视为常规字符进行显示输出,例如下列代码:
cout<<" today is \"Thursday\" , Crazy Thursday"<<endl;
输出的内容将是 today is "Thursday", Crazy Thursday
\b ——退格,使光标回退一格
也可以基于字符的八进制和十六进制使用转义序列,例如Ctrl+Z的ASCII码为26,对应的八进制编码为032,对应的十六进制编码为0x1a,可以用\032和\0x1a来表示该字符,将对应的转义序列用单引号扩起,可得到相应的字符常量,如 '0x1a' ,也可跟上述转义序列一样,直接放到字符串中,形如"say\0x1a hello"
注意:在可以使用数字转义序列或符号转义序列(如\0x8和\b)时,应使用符号转义序列,原因是符号适用于任何编码方式,且可读性也更强
未完待续...