C++学习day--15 指针

在学习指针之前,有些话要说一下:

方圆之道 - 做人要方,做事要圆“,做人要方方正正,有自己的边界和原则,做事要用心,不要有 棱角,尽量做的圆满!!
1. 不要跟直接领导起冲突
2. 你站的一方,有利益并且对你好
3. 你站的一边,背后有更大的靠山
4. 你站的一边,没有人和你有利益冲突
5. 如果缺乏以上的判断力,请保持佛系-中立

 防御式编程:

防御式编程( Defensive Programming 是提高软件质量的辅助手段 怎么理解呢?防御式编程思想的理解可以参考防御式驾驶:
在防御式驾驶中要建立这样一种思维,那就是你水远也不能确定另一位司机将要 做什么。这样才能确保在其他人做出危险动作时你也不会受到伤害。你要承担起 保护自己的责任,哪怕是其他司机犯的错误。
核心思想: 子程序应该不因传入错误数据而被破坏,哪怕是由其他子程序产生的错误数据。这种思想是将可能出现的错误造成的影响控制在有限的范围内。

具体措施:

1. 对输入进行体检
1 )检查输入源(如:文件,网络、控制台等)数据的合法性
(2)检查每一个函数输入参数的合法性
处理方式: 一旦非法输入被发现,那么应该根据情况进行处理。防御式编程的最佳的形式是在一开始就不引入错误。
2. 对非预期错误使用断言
1 )空指针。
(2)输入或者输出参数的值不在预期范围内。
(3)数组的越界。
处理方式: 如果断言的条件返回错误,则终止程序执行。 断言原型定义:
#include
void assert( int expression )
assert 的作用是先计算表达式 expression ,如果其值为假(即为 0 ),那么它先向stderr 打印一条出错信息, 然后通过调用 abort 来终止程序运行。

 例如上节课做的那个项目判断峰点时可以使用断言:

bool isPeak(int grid[N][N], int r, int c) {
	assert(0 < r && r < N - 1);
	assert(0 < c && c < N - 1);
	if ((grid[r][c] > grid[r - 1][c]) &&
		(grid[r][c] > grid[r + 1][c]) &&
		(grid[r][c] > grid[r][c - 1]) &&
		(grid[r][c] > grid[r][c + 1])) {
		return true;
	}
	else {
		return false;
	}
}

进入今天的主题:指针!!

1. 为什么要使用指针

1、函数的值传递,无法通过调用函数,来修改函数的实参
2、被调用函数需要提供更多的“返回值”给调用函数,靠值传递行不通
3、减少值传递时带来的额外开销,提高代码执行效率

我们看一个代码:

#include
using namespace std;
void add_blood(int blood) {
	blood += 1000;
}

int main() {
	int blood = 90;
	add_blood(blood);
	cout << blood << endl;
}

运行结果:

C++学习day--15 指针_第1张图片

这个运行结果说明不能通过传递值来改变实参的值。

把代码更新一下:

#include
using namespace std;
int add_blood(int blood) {
	blood += 1000;
	return blood;
}

int main() {
	int blood = 90;
	add_blood(blood);
	cout << blood << endl;
	blood=add_blood(blood);
	cout << blood << endl;
}

运行结果:

 C++学习day--15 指针_第2张图片

虽然函数可以通过返回类型来改变值,但是如果在主函数中不更新变量,那么该变量的值还是不会改变,如我们仅仅只是调用add_blood()函数,是不会改变实参的值!要把返回的值赋值给该变量才能改变! 

那么能不能不通过返回值就直接改变实参的值呢?答案是可以,用指针!

看一个代码,来理解指针的定义:

#include 
#include 
int main(void) {
	int age;
	char ch;
	int* p;//定义一个int型指针
	char* c;//定义一个char型指针
	p = &age;//指针p指向了age,p的值就是age的地址
	c = &ch;
	scanf_s("%d", p);//等价于scanf_s("%d", &age);
	printf("age: %d\n", age);
	system("pause");
	return 0;
}

运行结果:

 C++学习day--15 指针_第3张图片

 指针的定义:数据类型* 指针变量名,例如:int *p;
 指针本身也是一个变量,用来存储地址,不能用来存储其他数据!
 名称是 p, 它是一个指针,可以指向一个整数变量的地址。
 也就是说: p 的值就是一个整数的地址!!!

画个图理解:

int age=18;

int *p=&age;

C++学习day--15 指针_第4张图片

 假如变量age的地址是888,那么指针p的值就是888,它存的是age的地址,我们也可以说指针p指向了变量age。

指针的定义:

第一种定义方式:
int *p;
int *p1, *p2;  定义两个指针变量,推荐这种定义方式!
第二种定义方式:
int* p;
int* p1,p2; 注意,这里不是一下子定义了两个指针变量,p1 是指针, 但是 p2 只是整形变量,这里很容易出错,因此一个好的定义方式是方式1。把*和变量名写在一块,可增强代码可读性!
第三种定义方式:
int * p; 不常用
第四种定义方式int*p;    不建议这种定义,可读性差!

指针的初始化

#include 
#include 
int main(void) {
	int room = 2;
	//定义两个指针变量指向 room
	int* p1 = &room;
	int* p2 = &room;
	printf("room 地址:0x%p\n", &room);
	printf("p1 地址:0x%p\n", &p1);
	printf("p2 地址:0x%p\n", &p2);
	printf("p1 的值是%p\n", p1);
	printf("p2 的值是%p\n", p2);
	printf("room 所占字节:%d\n", sizeof(room));
	printf("p1 所占字节:%d\n", sizeof(p1));
	printf("p2 所占字节:%d\n", sizeof(p2));
}

运行结果:(我这里实在64位平台下运行的!) 

C++学习day--15 指针_第5张图片

 先声明一点!指针变量所占的字节大小在32位平台是4个字节,在64位平台是8个字节!可以看到p1和p2的值就是变量room的地址。

画图理解:

C++学习day--15 指针_第6张图片

注意:再次强调!
32 位系统中,int 整数占 4 个字节,指针同样占 4 个字节
64 位系统中,int 整数占 4 个字节,指针同样占 8 个字节

 指针的访问

先看一个代码:地址的打印

#include 
#include 
int main(void) {
	int room1 = 2;
	int room2 = 3;
	int* p1 = &room1;
	int* p2 = p1;//等价于int *p2 = &room1;
	//1.访问(读、写)指针变量本身的值,和其它普通变量的访问方式相同
	int* p3 = p1;
	printf("room 的地址: %p\n", &room1);
	printf("p1 的值: %p p2 的值: %p\n", p1, p2);
	printf("p3 的值: %p\n", p3);
	printf("--------------------\n");
	p3 = &room2;
	printf("p3 的值: %p, room2 的地址:%p\n", p3, &room2);
	printf("p1=0x%p\n", p1);
	printf("p1=0x%x\n", p1);
	printf("p1=0x%X\n", p1);
}

运行结果:

C++学习day--15 指针_第7张图片

 这里没啥好说的,理解即可,主要就是地址是一个无符号数,我们一般用%p打印,%x也是打印16进制的数,但是还是建议用%p,通过上面我们看到,%x或者%X它虽然是以16进制打印数据,但是它不能自动填充0。所以打印地址还是用%p格式打印!

%p可以在前面自动补0,如果一个地址换成16进制 后只有6位,那么%p形式会自动在前2个位置补0,而 %x不会自动补0。

 再看代码,指针的解引用:

#include 
#include 
int main(void) {
	int room = 2;
	int* girl = &room;
	int x = 0;
	x = *girl;// *是一个特殊的运算符,*girl 表示读取指针 girl 所指向的变量的值, * girl 相当于 room
	printf("x: %d\n", x);
	*girl = 4; //相当于 room = 4
	printf("room: %d, *girl: %d\n", room, *girl);
}

运行结果:

 C++学习day--15 指针_第8张图片

这个结果说明,*gril等价于room,对*girl改变就是改变room。我们在定义的时候符号*是起到定义指针的作用,在非定义时,它是解引用和乘法操作符号。看图理解: 

C++学习day--15 指针_第9张图片

 

你可能感兴趣的:(C++学习——奇牛学院,学习)