指针: 存储值的地址
的变量
初始化指针
int* p;
将int
和*
放在一起, 强调的是: 一个指向int
的指针
*
解除引用运算符: 使用时, 表示指针指向的那个值
&
地址运算符: 获取值的地址
指针赋值
给指针赋值的两种方式: 1️⃣先初始化, 后赋值 2️⃣初始化指针的同时给指针赋值
int* p;
int a = 123;
p = &a;
int a = 123;
int* p = &a;
cout << "值 " << a << endl;
cout << "值 " << *p << endl;
cout << "地址 " << &a << endl;
cout << "地址 " << p << endl;
cout << "地址的地址 " << &p << endl;
值 123
值 123
地址 0x61fe1c
地址 0x61fe1c
地址的地址 0x61fe10
使用一个未初始化的指针, 可能会报 Segmentation fault
int* p1;
cout << "Segmentation fault" << *p1 << endl;
链式指针
int **p2;
int *p1;
int n = 123;
// 添加一个地址(p1)给 p2 (第一张图片中)
p2 = &p1;
// 添加一个地址(n)给 p1 (第二张图片中)
*p2 = &n;
cout << "p2 的地址" << &p2 << endl;
cout << "指针 p1 的地址" << p2 << endl;
cout << "n 的地址" << *p2 << endl;
cout << "n 的地址上的值" << **p2 << endl;
// 修改地址上的内容, 即修改 n 的值
*p1 = 10;
p2 的地址0x61fe18
指针 p1 的地址0x61fe10
n 的地址0x61fe0c
n 的地址上的值123
**p2
: 链式地址, 即地址上存的还是地址
数组名
c++
将数组名
解释为数组中第一个元素地址
, 所以可将数组名
理解为一个指针
指针 + 1 , 等于 指针原来的地址值
+ 指向对象占用的字节数
int arr[3] = {1, 2, 3};
// 0x61fe14 第一个元素的地址
cout << arr << endl;
// 1 第一个元素的值
cout << *arr << endl;
// 1 第一个元素的值
cout << arr[0] << endl;
// 0x61fe18 第一个元素的地址 + 4 => 第二个元素的地址
cout << arr + 1 << endl;
// 2 第二个元素的地址上的值
cout << *(arr + 1) << endl;
函数声明
- 函数原型
- 函数定义
- 调用函数
如下为调用一个数组之和的函数
#include <iostream>
using namespace std;
// 函数原型
int total(int arr[], int n);
int main()
{
int arr[3] = {1, 2, 3};
// 调用函数
int res = total(arr, 3);
// 6
cout << res << endl;
// 12346
cout << arr[0] << endl;
}
// 函数定义
int total(int arr[], int n)
{
int total = 0;
for (int i = 0; i < n; i++)
total += arr[i];
arr[0] += 12345;
return total;
}
因为传给函数的数组名为一个地址
, 因此, 在函数内部, 可更改数组的值
const 保护数组
// 函数原型
int total(const int arr[], int n);
// 函数定义
int total(const int arr[], int n)
{
int total = 0;
for (int i = 0; i < n; i++)
total += arr[i];
// error: assignment of read-only location '* arr'
// arr[0] += 12345;
return total;
}
此时, 该函数将数组
视为只读数据
可以看到, c++编译器
将arr[]
解释为*arr
, 说明const int arr[]
与cosnt int* arr
含义完全相同
// 函数原型
int total(const int* arr, int n);
// 函数定义
int total(const int* arr, int n)
{
int total = 0;
for (int i = 0; i < n; i++)
total += arr[i];
return total;
}
在函数原型
中, 可以省略标识符
// 函数原型
int total(const int*, int n);
指针和 const
const int*
将一个变量
赋值给一个const 指针
, 表明 *p
的值为 const
, 不能修改
int age = 18;
const int* p = &age;
// 报错: assignment of read-only location '* p'
// *p = 19; // 使用指针修改值, 报错
age = 19; // 成功
const int* p => *p 为 const 不可修改值
int* const
const
在 int*
后面, 意味着不可以修改指针的指向, 表明p
为const
int age = 18;
int* const p = &age;
*p = 19; // 可以修改值
// 报错: assignment of read-only variable 'p'
// p = 123; // 不可以修改指针的指向
int* const p => p 为 const 不可修改指向
const int* const
值
和指向
都不可修改
int age = 18;
const int* const p = &age;
// error: assignment of read-only location '*(const int*)p'
*p = 123; // 修改值, 报错
// error: assignment of read-only variable 'p'
p = 123; // 修改指向, 报错
常量 => 指针
将一个常量
赋值给一个指针
, 会报错
const int age = 18;
// 报错: invalid conversion from 'const int*' to 'int*'
int* p = &age; // 常量不可赋值给非 const 指针
如果上述语句成功, 意味着你可以使用*p
修改age
的值, 这是不正确的
函数指针
函数也有地址, 所以, 函数指针: 指向一个函数地址
的指针
int (*pf)(int);
pf 为指向函数的指针
#include <iostream>
void foo();
int main()
{
void (*pf)(); //声明函数指针
pf = foo;
// 调用函数指针的两种方式
pf(); // 指向函数的指针的行为应与函数名相似
(*pf)(); // *pf 是函数, (*pf)()用作函数调用
}
void foo(){
std::cout << "foo" << std::endl;
}
将数组名当作参数
#include <iostream>
const int *f1(const int *, int n);
const int *f2(const int *, int n);
const int *f3(const int *, int n);
int main()
{
using namespace std;
const int arr[3] = {1, 2, 3};
const int *(*p3)(const int *, int n) = f3; // 定义一个指向 f3 的函数指针
cout << "Address Value\n";
cout << f1(arr, 3) << ": " << *f1(arr, 3) << endl;
cout << f2(arr, 3) << ": " << *f2(arr, 3) << endl;
cout << p3(arr, 3) << ": " << *p3(arr, 3) << "\n" << endl;
const int *(*pa[3])(const int *, int n) = {f1, f2, f3}; // 定义一个函数指针数组
auto pb = pa; // pb 指向 pa 的第一个元素
cout << pa[0](arr, 3) << ": " << *pa[0](arr, 3) << endl;
cout << pa[1](arr, 3) << ": " << *pa[1](arr, 3) << endl;
cout << pb[2](arr, 3) << ": " << *pb[2](arr, 3) << endl;
}
const int *f1(const int *arr, int n)
{
return arr;
}
const int *f2(const int *arr, int n)
{
return arr + 1;
}
const int *f3(const int *arr, int n)
{
return arr + 2;
}