const关键字

1.修饰内置类型

内置类型就是int double这些类型

1
2
const double pi = 3.14;//const起到了一个只读的限定的作用
pi = 23.8;//error 被const修饰无法修改

const比起宏定义的好处:宏定义没有类型检查,但是const是有类型检查的

被const修饰的变量必须要初始化,不能单独存在

1
const int a;//error 必须要初始化

面试常考题

const和宏定义常量的区别

1.发生的实际不同:c语言的宏定义的发生时间在预处理时,const常量实在编译时

2.类型和安全检查不同:宏定义没有类型检查,const有

2.修饰指针类型

const修饰的三种形式

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
int num1 = 100;
int num2 = 100;
//前两种称为指向常量的指针--pointer to const
const int *a = &num1;//通过指针修改内容是不允许的
*a = &200;//error 不允许修改指针指向的内容,
a = &num2;//可以的 允许修改指针指向
int const *b = &num1;//同上 不允许修改指针指向的内容,但是允许修改指针指向
const int num3 = 1;
int *p = &num3;//error 不允许,只有指向常量的指针才能去指向const常量
//总结:指向常量的指针不仅能够指向const常量,还可以指向普通的变量


//常量指针 const pointer
int * const c = &num1;
*c = 200;//可以修改
c = &num2;//不可以修改指针指向,可以理解为const修饰的是指针本身

const int num4 = 1;
int * const d = &num4;//error
const int * const e = &num4;

3.数组指针和指针数组

数组指针:指向数组的指针,管理权是整个数组空间

1
2
3
4
5
6
7
8
9
10
//定义数组指针
int arr[3] = {1,2,3};
int (*p)[3] = &arr;//个数也必须和数组对应

//arr + 1和&arr + 1两者不一样,第一个偏移一个元素的长度,第二个偏移一个数组的长度

//利用数组指针遍历数组
for(int i = 0; i < 3; ++i){
cout << (*p)[i] << endl;//取下标的优先级比解引用高,所以要加括号,先解引用再取下标
}

指针数组:数组的元素是指针的数组

1
2
3
4
5
6
7
8
9
int num1 = 1, num2 = 2, num3 = 3;
int *p1 = &num1;
int *p2 = &num2;
int *p3 = &num3;
int *arr[3] = {p1, p2, p3};

for(int i = 0; i < 3; ++i){
cout << *arr[i] << endl;//与上面类比
}

4.函数指针和指针函数

函数指针

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
void print(){
cout << "print()" <<endl;
}
//函数指针
void test(){
//定义函数指针要确定指向的函数类型和参数信息
void (*p)() = print;//()表示没有参数
p();

void (*p2)() = &print;
(*p2)();//上面的完整写法,解引用就是把找到函数代码的区域,然后加个括号调用函数
//函数类型必须对应,否则没法修改指针指向也就是说,指针的必须是void返回值,且无参的函数
}

//例2
int dispaly(int x,int y){
cout << x + y <<endl;
return x+y;
}

void tese2(){
int (*p3)(int ,int) = &display;
(*p3)(1,2);

}

指针函数:函数返回值是指针的函数

1
2
3
4
5
6
7
8
9
int Num = 600;
int *f(){
return &NUM;//返回的地址必须比函数本身的生存周期长
}

int *f2(){
int Num2 = 100;
return &Num2;//error 函数调用完就被销毁了,指针指向的是不确定的值
}