作为记录下本次c++学习过程
一、指针部分(因为涉及到指针函数,顺便复习一次指针)
何为指针:指针即是一个变量,该变量存放的是一个地址(来自:c++ Primer Puls)
我个人是比较赞同这一个说法,下面我会通过代码来解释我是如何理解这个观点。
1.指针指向变量
实现效果:a的值等于*p的值,&a的值等于p的值
#include <iostream>
//#include<string.h>
//#include<stdio.h>
using namespace std;
int main()
{
int a = 10;
int* p;
//记住指针同样是变量,存放的是地址
//p = a; //此写法错误,a是变量,此时p存放的是变量a,是一个数值
p = &a;//此写法正确,“&”为运算符,获取该变量的地址,此时p存放的是a的地址
cout << "a:" << a << endl;
cout << "&a:" << &a << endl;
cout << "p:" << p << endl;
cout << "*p:" << *p << endl;
//前面说指针其实就是一个变量,那么这个变量同样是有一个存放的地址
cout << "&p: " << &p << endl;
return 0;
}
2.指针指向一维数组
#include <iostream>
//#include<string.h>
//#include<stdio.h>
using namespace std;
int main()
{
int a[8] = {1,3,5,7,9,11,13,15};
/*
首先要知道一点,当你初始化一个数组之后,该数组会按照初始化的大小,分配出一个对应大小的空间。
int类型的变量是4个字节,那对应此数组就有需要占用32个字节
*/
//在指针指向数组前,先看下数组a的信息,以第一个值作为演示
cout << "(sizeof)a: " << sizeof(a) << endl;//数组a占用的长度
cout << "(sizeof)int: " << sizeof(int) << endl;//一个int整型占用的长度
//在一维数组中a和&a没有本质上的差别,都是数组的第一个元素,但是同样+1之后就会有本质上的差别
cout << "a: " << a << endl;
cout << "&a: " << &a << endl;
cout << "a+1: " << a+1 << endl;//数组a的下一个整型的起始地址
cout << "&a+1: " << &a+1 << endl;//与数组a相同大小(32个字节)的下一个数组的起始地址,也可以认为是数组a结束地址
//cout << "&(a+1): " << &(a+1) << endl; //此写法不被允许
cout << "a[0]: " << a[0] << endl;
cout << "&a[0]: " << &a[0] << endl << endl;
//对于一维数组要有本质上的理解,才可以更好的理解指针数组,当然也可以死记,不去追究
//
//记住指针同样是变量,存放的是地址
int* p1 = a;
//int* p2 = &a;//此写法不被允许
//int* p3 = a[0];//此写法不被允许
int* p4 = &a[0];
cout << "p1: " << p1 << endl;
cout << "&p1: " << &p1 << endl;
cout << "*(&p1): " << *(&p1) << endl;
cout << "*(*(&p1)): " << *(*(&p1)) << endl;
cout << "&p1+1: " << &p1+1 << endl;
cout << "*(&p1+1): " << *(&p1 + 1) << endl;
//cout << "&(p1+1): " << &(p1+1) << endl;//此写法不被允许
cout << "*p1: " << *p1 << endl;
cout << "*p1+1: " << *p1 + 1 << endl;
cout << "*(p1+1): " << *(p1+1) << endl << endl;
cout << "p4: " << p4 << endl;
cout << "&p4: " << &p4 << endl;
cout << "*(&p4): " << *(&p4) << endl;
cout << "*(*(&p4)): " << *(*(&p4)) << endl;
cout << "&p4+1: " << &p4 + 1 << endl;
cout << "*(&p4+1): " << *(&p4 + 1) << endl;
//cout << "&(p4+1): " << &(p4+1) << endl;//此写法不被允许
cout << "*p4: " << *p4 << endl;
cout << "*p4+1: " << *p4 + 1 << endl;
cout << "*(p4+1): " << *(p4 + 1) << endl;
return 0;
}
指针过程解释(从编译的角度进行理解):
①int* p1 = a;//指针p1指向数组a的首地址
int* p4 = &a[0];//指针p4指向数组a的起始地址
②&p1、&p4//代表的是存放指针的地址(指针也是变量,是变量就要有地址存放),此处不深究
③*(&p1)、*(&p4)
看到 * 可以认为是指针的效果,注意只是效果!!。他们指向的是&p1、&p4里面的内容,结合②,可知*(&p1)、*(&p4)的值等价于p1、p4的值。
④*(*(&p1))、*(*(&p4)) 最终指向的就是数组a的第一个元素
这四个点要需要结合一些链表的思想才可以更好地理解
例如:
我有8本书按照1-8的编号,并按顺序放在了图书馆的2号书架第1-8层的。这天小红问我,想拿我的1号书,我应该怎么告诉小红(这就相当于怎么取出数组a的第一个元素)??
答:我在一张纸上写着图书馆2号书架第一层,那么小红想拿到那就首先需要拿到这一张纸,这一张纸在我这,找到我就相当于找到了这一张纸(我和纸是等价的),这就是第一个地址,即&p1=&我(纸张)。当小红拿到纸张后,就可以看到纸张内容(纸张内容等价图书馆2号书架第一层),这就是第二个地址,即*(&p1)=*(纸张内容)。最后根据纸张内容找到书籍,即*(*(&p1))= *(图书馆2号书架第一层)。这里我觉着已经是很清楚的讲解,用普通一点的就是套娃,相当于中国广东佛山市一样,你要知道中国,才会知道广东,最后才可以知道佛山,不然是不可能一下子知道佛山的。
⑤&p1+1、&p4+1 代表存放指针的地址+1,增加的长度是指针类型的长度,此处不深究
⑥*(&p1+1)、*(&p4+1) 代表存放指针的地址+1后的值,因为我都没有初始化,所以是系统随意赋值,此处不深究
⑦在一维数组中无论是a还是&a[0],都指向数组的首地址,所以*p1和*p4、*p4+1和*p1+1、*(p1+1)和*(p4+1)三者相互之间等价。
3.指针指向二维数组(与一维数组同解)
#include <iostream>
//#include<string.h>
//#include<stdio.h>
using namespace std;
int main()
{
int a[4][3] = {
{1,3,5,},
{9,11,13},
{2,4,6},
{10,12,14}
};
//二维数组赋值同样,指针存储的是第一个元素(是二维元素里的)的地址,如下
int* p1 = a[0];
int* p4 = &a[0][1];
cout << "p1: " << p1 << endl;
cout << "&p1: " << &p1 << endl;
cout << "*(&p1): " << *(&p1) << endl;
cout << "*(*(&p1)): " << *(*(&p1)) << endl;
cout << "&p1+1: " << &p1 + 1 << endl;
cout << "*(&p1+1): " << *(&p1 + 1) << endl;
//cout << "&(p1+1): " << &(p1+1) << endl;//此写法不被允许
cout << "*p1: " << *p1 << endl;
cout << "*p1+1: " << *p1 + 1 << endl;
cout << "*(p1+1): " << *(p1 + 1) << endl << endl;
cout << "p4: " << p4 << endl;
cout << "&p4: " << &p4 << endl;
cout << "*(&p4): " << *(&p4) << endl;
cout << "*(*(&p4)): " << *(*(&p4)) << endl;
cout << "&p4+1: " << &p4 + 1 << endl;
cout << "*(&p4+1): " << *(&p4 + 1) << endl;
//cout << "&(p4+1): " << &(p4+1) << endl;//此写法不被允许
cout << "*p4: " << *p4 << endl;
cout << "*p4+1: " << *p4 + 1 << endl;
cout << "*(p4+1): " << *(p4 + 1) << endl;
return 0;
}
4.指针指向结构体
结构体指针算是比较好理解的,就是注意const的用法,修饰谁,谁就无法通过指针改变
#include <iostream>
#include<string.h>
//#include<stdio.h>
using namespace std;
struct student
{
char name[10];
char gender[10];
int age;
};
//结构体指针,结合const一起使用
void s2_message_change(const student S1,student *S2)
{
strcpy_s(S2->name,S1.name);
strcpy_s(S2->gender,S1.gender);
S2->age = S1.age;
}
int main()
{
//定义两个结构体
struct student s1;
struct student s2;
student* p; //定义结构体指针
p = &s2; //指针一定是存放地址!!
//结构体赋值
strcpy_s(s1.name, "张三");
strcpy_s(s1.gender, "男");
s1.age = 18;
strcpy_s(p->name, "李四");
strcpy_s(p->gender, "女");
p->age = 20;
cout << "s1.name: " << s1.name << endl;
cout << "s1.gender: " << s1.gender<< endl;
cout << "s1.age: " << s1.age << endl << endl;
cout << "s2.name: " << s2.name << endl;
cout << "s2.gender: " << s2.gender << endl;
cout << "s2.age: " << s2.age << endl << endl;
cout << "p->name: " << p->name << endl;
cout << "p->gender: " << p->gender << endl;
cout << "p->age: " << p->age << endl << endl;
s2_message_change(s1, p);
cout << "p->name_change: " << p->name << endl;
cout << "p->gender_change: " << p->gender << endl;
cout << "p->age_change: " << p->age << endl << endl;
return 0;
}
5.指针指向函数
#include <iostream>
//#include<string.h>
//#include<stdio.h>
using namespace std;
double betsy(int);
double pam(int);
void estimate(int line, double (*pf)(int));
//定义两个返回函数
double betsy(int lns)
{
return 0.05 * lns;
}
double pam(int lns)
{
return 0.03 * lns + 0.0004 * lns * lns;
}
void estimate(int line, double (*pf)(int))
{
//*pf 代表传入的函数,(int)代表传入该函数的值,要与返回函数定义的相匹配
cout << line << "lines will take\n";
cout << (*pf)(line) << "hour(s)\n";
}
void main()
{
int code;
while (1)
{
cout << "How much lines of code do you need?\n";
cin >> code; //输入一个整型值计算
cout << "Here is Betsy's estimate:\n";
estimate(code, betsy); //指针函数传入并返回输出
cout << "Here is Pam's estimate:\n";
estimate(code, pam); //指针函数传入并返回输出
}
}