2 变量和基本类型
2.1 基本内置类型
C++定义了一系列包括算术类型(arithmetic type)和空类型(void)在内的基本数据类型。其中算术类型包含字符,整型数,布尔值和浮点数。空类型不对应具体的值,当函数不需要返回任何值时,使用空类型作为返回类型。下表是C++的七种基本数据类型。
类型 |
含义 |
最小尺寸 |
位 |
bool |
布尔类型 |
未定义 |
|
char |
字符型 |
8 |
1个字节 |
wchar_t |
宽字符 |
16 |
2或4个字节 |
int |
整型 |
16 |
4个字节 |
float |
单精度浮点型 |
6位有效数字 |
4个字节 |
double |
双精度浮点型 |
10位有效数字 |
8个字节 |
void |
无类型 |
null |
布尔类型(bool)的取值为真(true)或者假(false)。
一些基本类型可用一个或多个类型修饰符进行修饰:
- signed(带符号的)
- unsigned(无符号的)
- short(字节/2)
- long(字节*2)
2.2 变量
变量提供一个具名的,可供程序操作的存储空间。即告诉编译器在何处创建变量的存储,以及如何创建变量的存储。对C++程序员来说,变量(variable)和对象(object)一般可以互换使用。
2.2.1变量定义
变量定义指定一个数据类型,并包含了该类型的一个或多个变量的列表。其基本形式是: 类型说明符 变量名1,变量名2,...;
当对象在创建时获得了一个特定值,我们就说这个对象被初始化。注意:初始化不是赋值,初始化是创建变量时赋予其一个初始值,赋值是把对象当前值擦除,而已一个新值替代。
2.2.2变量声明和定义的关系
为了允许把程序拆分成多个逻辑部分来编写,C++语言支持分离式编译机制,该机制允许将程序分割成若干个文件,每个文件可被独立编译。而为了支持分离式编译,C++语言将声明和定义区分开来。
声明(declaration)使得名字为程序所知,一个文件如果想使用别处定义的名字就必须包含对那个名字的声明。定义(definition)负责创建与名字关联的实体。
如:extern int i; //声明i,不定义
extern int i=0;//定义i
2.2.3标识符
C++标识符(identifier)由字母,数字和下划线组成,其中必须由字母或下划线开头。对小大写敏感。关键字与操作符不可被作为标识符。
变量命名约定俗成的规范:
- 标识符要能体现实际含义
- 变量名一般用小写字母
- 用户自定义的类名一般以大写字母开头
- 标识符由多个字母组成,单词间应有明显区分,如下划线,大写单词第一个字母
2.2.4名字的作用域
作用域是程序的一部分。同一个名字在不同的作用域中可能指向不同的实体,名字的有效区域始于名字的声明语句,以声明语句所在的作用域末端结束。
2.3 复合类型
复合类型(compound type)是指基于其他类型定义的类型。C++主要用到的就是引用和指针。
2.3.1 引用
引用(reference)为对象起了另外一个名字,即别名。引用类型引用(refers to)另外一种类型。通过将声明符写成&d的形式来定义引用类型,其中d为类型的变量名。
一般在初始化变量时,初始值会被拷贝到新建的对象中。然而定义引用时,程序把引用和它的初始值绑定在一起,而不是将初始值拷贝给引用。一旦初始化完成,引用将和它的初始值对象一直绑定在一起。因为无法令引用重新绑定到另外一个对象,因此引用必须被初始化。
2.3.2指针
指针(pointer)是指向(point to)另外一个类型的复合类型。指针本身就是一个对象,允许对指针赋值和拷贝;指针无须在定义时赋初值。但建议要初始化指针。
指针是一个变量,其值为另一个变量的地址,即,内存位置的直接地址。就像其他变量或常量一样,您必须在使用指针存储其他变量地址之前,对其进行声明。指针变量声明的一般形式为:
type *var-name;
其中type 是指针的基类型,它必须是一个有效的 C++ 数据类型,var-name 是指针变量的名称。
获取对象地址
取地址符(&),可获取指针存放某个对象的地址。
指针值
指针值(即地址)应属于以下四种状态之一;
- 指向一个对象
- 指向紧邻对象所占空间的下一个位置
- 空指针,意味着指针没有指向任何对象
- 无效指针,除上述情况之外的其他值
利用指针访问对象
解引用符(*)访问指针指向的对象。仅适用某个对象的有效指针。
注:在声明语句中,&和*用于复合类型;在表达式中,&和*用于运算符。
空指针
空指针(null pointer)不指向任何对象。得到空指针可用字面值nullptr来初始化指针,也可将指针初始化为字面值0。过去用null的预处理变量来给指针赋值。其头文件为cstlib。
2.3 const限定符
Const对象一旦创建后其值就不能再改变,const对象必须初始化。
2.4 处理类型
2.4.1 类型别名
类型别名(type alias)是某种类型的同义词。两种方式定义类型别名:
- 使用关键字(typedef )typedef type newname;
- 使用别名声明(alias declaration)using newname=type;
2.4.2 指针、常量和类型别名
typedef char *pstring;//pstring是类型char*的别名,即指向char的指针
const pstring cstr=0;//cstr是指向char的常量指针
const pstring *ps; //ps是一个指针,它的对象是指向char的常量指针
2.5 自定义数据结构
定义结构
为了定义结构,您必须使用 struct 语句。struct 语句定义了一个包含多个成员的新的数据类型,struct 语句的格式如下:
struct type_name {
member_type1 member_name1;
member_type2 member_name2;
member_type3 member_name3;
.
.
} object_names;
type_name 是结构体类型的名称,member_type1 member_name1 是标准的变量定义,比如 int i; 或者 float f; 或者其他有效的变量定义。在结构定义的末尾,最后一个分号之前,您可以指定一个或多个结构变量,这是可选的。
访问结构成员
为了访问结构的成员,我们使用成员访问运算符(.)。成员访问运算符是结构变量名称和我们要访问的结构成员之间的一个句号。
预处理区概述
通常我们说C++的Build(这里没用“编译”是怕混淆)可分为4个步骤:预处理、编译、汇编、链接。预处理就是本文要详细说的宏替换、头文件包含等;编译是指对预处理后的代码进行语法和语义分析,最终得到汇编代码或接近汇编的其他中间代码;汇编是指将上一步得到的汇编或中间代码转换为目标机器的二进制指令,一般是每个源文件生成一个二进制文件(VS是.obj,GCC是.o);链接是对上一步得到的多个二进制文件“链接”成可执行文件或库文件等。
Preprocessor指令一般格式如下:
# preprocessing_instruction [arguments] newline
其中preprocessing_instruction是以下之一:define, undef, include, if, ifdef, ifndef, else, elif, endif, line, error, pragma;arguments是可选的参数,如#include后面的文件名;Preprocessor占一行,可用“\”紧跟newline续行,但续行不是Preprocessor的专利,且续行在Preprocessor前处理。
Preprocessor指令有以下几种:
- Null,一个 # 后跟 newline ,不产生任何影响,类似于空语句;
- 条件编译,由 #if, #ifdef, #ifndef, #else, #elif, #endif 定义;
- 源文件包含,由 #include 定义;
- 宏替换,由 #define, #undef, #, ## 定义;
- 重定义行号和文件名,由 #line 定义;
- 错误信息,由 #error 定义;
- 编译器预留指令,由 #pragma 定义。