第二章 变量和基本类型
1.基本内置类型
包括算术类型和空类型,算术类型分为整型(包络字符和布尔类型在内)和浮点型。
地址是一个数字,根据他可以找到内存中的一个字节。
1.算术类型
机器实现:计算机由比特序列存储数据,大多数机器的1字节=8比特,1字=4/8字节=32/64比特,可寻址的最小内存块称为字节,存储的基本单元称为字。大多数计算机将内存中每一个字节和一个数字(地址)关联起来,所以我们能够使用某个地址表示从这个地址开始的大小不同的比特串,不同数据类型所占比特数不同,所以数据类型很重要。
除过布尔和扩展字符,其它整型分为有符号数(signed,可表示正数负数和0)和无符号数(仅能表示大于0的值)。int, short,long, long long本身是带符号的, 而char 和signed char不一样。
unsigned int可以缩写为unsigned。
浮点数运算一般选用double。
2.类型转换
程序自动类型转换:1.非布尔→布尔,初始值为0结果为false, 否则为true,非布尔值作为条件也一样(int i=0;if(i)这种
2.布尔→非布尔,初始值为false则结果为0,为true则结果为1
3.浮点数→整数,仅保留小数之前
4.整数→浮点,小数部分为0
5.赋给无符号数超出其表示范围的值,结果是初始值对无符号类型表示总数取模后的余数。 unsigned char=-1,结果是-1%256=255(取模运算时,对于负数,应该加上被除数的整数倍,使 结果大于或等于0之后,再进行运算,也就是:(-1)%256 = (-1+256)%256=255%256=255 )
6.赋给有符号数超出其表示范围的值,结果是undefined。
如果表达式里既有无符号数又有有符号数,会出现异常结果,有符号数会转换为无符号数。
3.字面值常量
一看就知道是什么的值叫字面值常量。
默认情况下,十进制字面值带符号;八进制和十六进制可以带符号也可以无符号;数据类型都是能容纳当前值的尺寸最小的数据类型。默认浮点字面值是double。
单引号括的为字符字面值,双引号括的为字符串字面值。编译器在字符串结尾会加一个\0,所以字符串字面值实际长度要加一。
2.变量
对象:一般认为是一块能存储数据并具有某种类型的内存空间。变量和对象一般可以交换使用。
注意:初始化≠赋值,赋值是把对象当前值擦除并以一个新值来代替。
初始化
列表初始化:c++11中用花括号初始化变量。int a{0},int a={0}
默认初始化:定义于函数体之外的变量默认初始化为0,之内不被初始化,值是未定义的,拷贝或者以其他形式访问会出错。
声明和定义
变量声明规定变量的类型和名字,定义会申请内存空间,还可能会赋值。
声明变量在变量名前添加关键字extern。如:extern int i,包含显示初始化的声明即为定义。
函数体内部初始化extern关键字标记的变量将引发错误。
变量只能被定义一次,但可以被声明多次。
标识符
由字母,数字,下划线组成,必须以字母或者下划线开头。不能连续出现两个下划线,不能下划线紧跟大写字母开头,函数体外标识符不能以下划线开头。
遵循命名规范
作用域
作用域声明了某个名字,那么它嵌套的所有作用域都能访问这个名字,而且内层可以重新定义。
使用作用域操作符::可以覆盖默认的作用域规则,访问想要访问的。
3.复合类型(引用和指针)
一条声明语句=数据类型+变量名列表,也即是基本数据类型+声明符。
1.引用(左值引用)
初始化是将初始值拷贝到新建对象中,定义引用时 程序把引用和它的初始值绑在一起 而不是将初始值拷贝给引用。所以引用必须初始化。
引用即别名。如 int ival=1; int &reival=ival; revial=2的操作就是把2赋给ival。对引用进行的操作都是在与之绑定的对象上进行的。
引用不是对象,所以不能定义引用的引用。
引用只能绑定在对象上,而不能是字面值(不能赋给数字这种值);定义引用的数据类型必须与对象匹配。
(例外:常量引用初始化可以用任意表达式,常量引用可以引用非常量对象)
2.指针
与引用相同之处:都实现了对对 象的间接访问。
与引用不同之处:1.指针本身是对象,可以对其赋值拷贝;2.指针在生命周期内可以指向不同的对象;3.指针定义无需初始化。
定义:*d,d是变量名。对d进行操作,就是改指针指向,对✳d操作就是改指针指向的地址的值。
获取对象地址:int ival=24; *int p=&ival;
定义指针的数据类型必须与对象匹配。
利用指针访问对象:*p=0,实际就是对p所指的对象赋值。
尽量等定义了对象后再定义指向它的指针,并且指针定义需要初始化。c++11中用 **nullptr **初始化。不能把int变量不取址直接赋给指针,即使是0也不行。
3.指针的指针和引用
& *这些都是声明符的修饰符,一般修饰符的个数没有限制。
**p表示指向指针的指针。
指针不能指向引用,但引用可以引用指针。int *p; int *&r=p; r是对指针p的引用。r=&i;r引用了指针,因此给r赋值就职令p指向i。
*int &r中从右向左读,离变量名最近的符号(&)对变量类型有最直接的影响,声明符其余部分用以确定r引用的类型是什么。
4.const限定符
格式为const int a=1
const默认仅在文件内有效,不同文件出现同名const变量等同于在不同文件中分别定义了独立的变量。如果想多文件共享,则在定义前添加extern关键字
1.const的引用(常量引用)
对常量的引用需要加const,因为不能让一个非常量引用指向常量对象;对常量的引用不能修改它的值。
2.指针和const
指向常量的指针需要加const。
指向常量的指针其指向的对象不一定是常量,只是不能通过指针改变该对象的值。
指向常量的指针或引用,只是它们自以为是,觉得自己指向了常量就不允许通过自己改变对象的值,其实对象不一定是常量。
3.指针常量和常量指针
常量指针:int *const a=&b;必须初始化,而且其值(即地址)不能再改变,不变的是指针本身;
指向常量的指针:const int *a=&b,不变的是指针所指的对象。
顶层const-----指针本身是个常量,也可以表示任意的对象时常量;
底层const-----指针所指的对象是常量。
4.constexpr和 常量表达式
值不会改变并且编译过程(不需要运行)就能得到结果的表达式。
如果认定变量是一个常量表达式,声明成constexpr类型。constexpr int mf=20
5.处理类型
1.类型别名
typedef关键字。包含typedef的声明语句定义的不再是变量而是类型别名。或者用using作为别名声明的开始。
typed int wages;wages a=0;
typed char ✳pstring,那么pstring就是类型char*的别名。
注意:pstring是指向char的指针,因此const pstring就是指向char的常量指针。而不能理解为const pstring s=const char *s,重写直接带入后,原来是声明一个指向char的常量指针,带入后变成了声明一个指向const char的指针。
auto类型说明符,需要把表达式的值赋给变量却不知道变量定义为什么数据数据类型时就可以用auto定义,编译器替我们分析表达式所属类型。
decltype类型指示符,返回表达式的数据类型。const int i=0,&b=i; decltype(b) y=x, 那么y的类型是const int&。decltype((变量))的结果永远是引用,decltype(变量)只有当变量本身是引用时才是引用。
6.自定义数据结构
类通常被定义在头文件中,且头文件名字应该和类一样。
预处理器
在程序编译过程中执行的一短程序。