重点易错点: const 指针
1.如何选择类型
- 在算术表达式中不要使用char或者bool,只有在存放字符或者bool时才去使用。因为char 因为机器的不同可能为有符号,也可能为无符号,直接使用char 容易出问题。
- 如果需要使用char 取值范围内的数值,最后明确指定用 signed char / unsigned char
- 执行浮点运算选double, 因为float 通常精度不够,而且双精度浮点和单精度浮点数的计算代价相差无几。
2.常量加后缀,指定字面值类型
整型字面值
- u/U unsigned
- l/L long
- ll/LL long long
浮点型字面值
- f/F float
- l/L long double
3.默认初始化
- 如果定义时没有指定初始值,则默认值由定义的位置以及变量的类型决定
- 内置类型由位置决定:函数内部将不被初始化,函数外部被初始化为0
4.变量定义与声明的关系
- 声明使得名字为程序所知,一个文件如果想使用别处被定义的名字则必须包含那个名字的声明。
- 定义负责创建与名字关联的实体
- 定义申请了内存空间
- 如果想声明而非定义,用 extern,且不要显示初始化变量
extern int i;// 声明而非定义
int j;//声明并定义 - 用extern 声明的变量如果被赋值,则变成了定义
extern int i;// 声明且定义
5.void *
- void * 是一种特殊指针类型,可以存放任意类型的对象的地址
- 一般用作函数的输入输出
6.复合类型的声明
- 要理解变量的类型最简单的办法,从右向左阅读定义,离变量最近的符号对变量的类型有最直接的影响
int i= 1;
int*p;
int *&i = p; // r是一个对指针p 的引用
r = &i;// r是一个对指针p 的引用,因此r 赋值&i, 就是令p 指向i
7.const的引用
- 对const 的引用可以引用一个并非const 的对象
int i= 1;
int &r1 = i;
const int &r2 = i // r2 绑定到对象i, 但是不允许通过r2 修改
r1 = 0; // 正常
r2 = 0; // error
8.指针和const
- 指向常量的指针不能用于改变其所指对象的值。
- 要想存放常量对象的地址,只能使用指向常量的指针
const double pi = 3.14;
double *p_pi = π // error
const *p_pi2 = π // 正常
*p_pi2 = 0; //error
- 允许一个指向常量的指针指向一个非常量对象(和常量引用一样)
double pi = 3.14;
const *p_pi2 = π // 正常
9.常量指针
- 指针是对象,也可以定为常量,常量指针必须初始化,和其他基本类型一样,一旦初始化就不能再改
- 指针本身是常量,但是其所指的对象可以是非常量,因此可以通过指针修改所指对象的值
- 非常量指针可以指向常量对象,该指针对象可以重新配置指向其他的对象,但是不能通过该指针更改对象的值
// 指针指向非常量对象
int i= 0;
int *const p_i = &i;
*p_i = 1;// 把p_i 所指的对象的值修改
// 指针指向常量对象
const int b= 0;
const int * p_b = &b;
*p_b = 1;// error
p_b = &i;//允许改变p_b 的值,指向其他对象
//常量指针指向常量对象
const int c= 0;
const int *const p_c = &c;
*p_c = 1;// error
- 注意用typdef 定义的指针,然后加const,定义的变量p_a 是指向非常量的常量指针
typedef int * i_p;
int main(){
int i = 9;
const i_p p_a = &i;
*p_a = 123;
const int * p_b = &i;
*p_b = 123;
return 0;
}