大纲要求
•【4】指针的概念及调用
•【4】指针与数组
•【4】字符指针与string类
•【4】指向结构体的指针
指针类型
指针是“指向(point to)”另外一种类型的复合类型。复合类型是指基于其它类型定义的类型。
指针**在 C++ 是保存另一个变量的存储器地址的变量。
引用**是一个已经存在的变量的别名。
一旦引用被初始化为一个变量,它就不能被更改为引用另一个变量。
理解指针,先从内存说起:内存是一个很大的、线性的字节数组。每一个字节都是固定的大小,由 8 个二进制位组成。最关键的是,每一个字节都有一个唯一的编号,编号从 0 开始,一直到最后一个字节。
程序加载到内存中后,在程序中使用的变量、常量、函数等数据,都有自己唯一的一个编号,这个编号就是这个数据的地址。
指针的值实质是内存单元(即字节)的编号,所以指针单独从数值上看,也是整数,他们一般用16进制表示。指针的值(虚拟地址值)使用一个机器字的大小来存储,也就是说,对于一个机器字为w位的电脑而言,它的虚拟地址空间是,程序最多能访问
个字节。这就是为什么 xp 这种 32 位系统最大支持 4GB内存的原因了。
用来保存指针的对象,就是指针对象。如果指针变量 p1 保存了变量 a 的地址,则就说:p1 指向了变量a,也可以说 p1 指向了 a 所在的内存块 ,这种指向关系,在图中一般用 箭头表示:
// 普通变量int a = 3;// 定义了变量a,int类型,值为3.内存中有一块内存空间是放a的值// 对a的存取操作,就是直接到这个内存空间存取// 内存空间的位置,叫地址// 存放 3 的地址,可以用 取地址操作符 & 得到,&a// 指针变量int *p = NULL;// 定义了一个指针变量 p,p指向一个内存空间,里面存放的是一个内存地址// 现在赋值为NULL(就是0,表示特殊的空地址),空指针// 申请一个空间给 p,*p内容不确定int *p = new(int);// 给指针变量 p 赋值, & 发音 andp = &a;// 把 a 变量的内存空间地址给了 p// 直接对 p 存取,操作的是地址// 通过这个地址,间接地操作,才是整数3// p的间接操作要使用指针操作符 *, *p 的值才是3
// 指针定义// 类型说明符 *指针变量名int a = 10;int *p;// 取地址运算符 &p = &a;// 间接运算符 *,解引用符 **p = 20;// 指针变量直接存取的是内存地址cout << p << '\n'; // 0x4097ce// 间接存取的才是存储类型的值cout << *p << '\n'; // 20
// *有靠近变量类型的,有靠近变量名称的// 有什么区别呢int *p;int* p;// *靠近哪一个都可以,编译器都会认为是指针变量,所以本质是一样的// 推荐靠近变量名称写 int *pint &ret;int& ret;// 这个也是同理
// 指针与引用#include <bits/stdc++.h>using namespace std;int main(){// 指针在声明后,无论何时都可以初始化为任意值// 可以分配一个指针来指向一个NULL值// 指针需要使用 *// 指针可以改为指向相同类型的任何变量int a = 5;int *p;p = &a;// or int *p = &a;cout << *p << '\n';// 引用被声明时必须进行初始化int b = 6;int &ref = b;cout << ref << '\n';return 0;}
引用符号的写法
#include<bits/stdc++.h>using namespace std;const int N = 10;int a[N][N];int main(){cout << a << '\n';cout << a[0] << '\n';cout << &a[0][0] << '\n';cout << &a[0][1] << '\n';cout << a[1] << '\n';cout << &a[1][0] << '\n';return 0;}/*0x1098d50c00x1098d50c00x1098d50c00x1098d50c40x1098d50e80x1098d50e8*/
指针与数组
// 下标法a[i];// 指针法*(a + i);
#include <bits/stdc++.h>using namespace std;const int N = 110;int a[N], n;int main(){cin >> n;for (int i = 0; i < n; i++) scanf("%d", a + i); //也可以这样读,编译有warningfor (int i = 0; i < n; i++) printf("%d ", *(a + i));puts("");return 0;}
指针与字符串
// 字符串的表示形式#include <bits/stdc++.h>using namespace std;int main(){char s1[] = "Hello s1!";printf("%s\n", s1);char *s2 = "Hello s2!"; // 把字符串的第1个元素的地址,赋值给了s2printf("%s\n", s2);return 0;}// %s 是输出字符串时用到的格式符,在输出项中,给出字符指针变量名,则系统先输出它所指的一个字符数据// 然后自动使 s2 加1,使之指向下一个字符// 然后再输出一个字符// 直到,遇到字符串结束标志'\0'为止
// 字符串指针,作为函数参数// 可以改变字符串里的内容#include <bits/stdc++.h>using namespace std;char s[110];void solve(char *s){int len = strlen(s);for (int i = 0; i < len; i++) s[i] -= 32;}int main(){scanf("%s", s);char *p = s;solve(p);printf("%s\n", s);return 0;}/*输入:abc输出:ABC*/// 下面这样写也是等价的#include <bits/stdc++.h>using namespace std;char s[110];void solve(char *s){int len = strlen(s);for (int i = 0; i < len; i++) s[i] -= 32;}int main(){scanf("%s", s);solve(s); //传递的时候,传递数组的名称,就是指针printf("%s\n", s);return 0;}// 下面这样写也是等价的#include <bits/stdc++.h>using namespace std;char s[110];void solve(char s[]){ //形参,写成char s[],这也是个指针int len = strlen(s);for (int i = 0; i < len; i++) s[i] -= 32;}int main(){scanf("%s", s);solve(s);printf("%s\n", s);return 0;}
指针与函数
// 指针作为函数参数#include <bits/stdc++.h>using namespace std;void swap(int a, int b){int t = a;a = b;b = t;}int main(){int a, b;cin >> a >> b;swap(a, b);cout << a << ' ' << b << '\n';return 0;}/*输入:3 4输出:3 4*/#include <bits/stdc++.h>using namespace std;void swap(int *a, int *b){int t = *a;*a = *b;*b = t;}int main(){int a, b;cin >> a >> b;swap(&a, &b);cout << a << ' ' << b << '\n';return 0;}/*输入:3 4输出:4 3*/
// 函数返回指针#include <bits/stdc++.h>using namespace std;int a[110], n, m;// int* find() 这样写的效果是一样的int *find(){for (int i = 0; i < n; i++)if (a[i] == m)return &a[i];return NULL;}int main(){cin >> n >> m;for (int i = 0; i < n; i++) cin >> a[i];int *p = find();if (p == NULL) printf("cannot find\n");else printf("%d %d\n", p, *p);return 0;}
结构体指针
// 引用结构体指针变量指向的结构体变量的成员的方法struct stu{int score;string name;}*p;指针名->成员名(*p).score;(*指针名).成员名p->score
// 自引用结构struct node{int x, y;node *next;}
字符指针
#include <bits/stdc++.h>using namespace std;const int N = 110;char s[] = "Hello";int main(){char *p = s;printf("%s\n", s);printf("%c\n", s[4]);printf("%c\n", *p);printf("%c\n", *(p + 4));printf("%c\n", *p + 4);cout << p << '\n';// 需要注意的是,字符串的以“\0”结尾,// 所以对于“Hello”这个字符串实际上含有6个字符// 因为表示字符串结尾标志的”\0“是自动添加的。for (int i = 0; s[i] != '\0'; i++) cout << s[i];puts("");return 0;}
// 字符串的创建,含有多种语法// 比较重要的一点是初始化时可以不指定数组长度char duckName[6] = {'D','a','v', 'i', 'd'};char duckName[6] = "David";char duckName[] = "David";
#include <bits/stdc++.h>using namespace std;const int N = 110;char s[N];void f1(char s[]){printf("%s\n", s);}void f2(char *s){for (; *s != '\0'; s++) printf("%c", *s);puts("");}int main(){scanf("%s", s);f1(s);f2(s);return 0;}
#include <bits/stdc++.h>using namespace std;const int N = 110;char s[N];int len;void f(char *s){for (int i = 0; i < len; i++) printf("%c", *(s + i));puts("");}int main(){scanf("%s", s);len = strlen(s);f(s);return 0;}


