初识 C++ 指针, 数组, 函数, 函数指针

本文详细探讨了指针作为存储地址的变量,介绍了初始化、*运算符、&运算符的应用,包括指针赋值的不同方式,链式指针,数组名与指针的关系,以及函数指针、const修饰指针的概念。重点讲解了指针和常量的交互以及函数指针的用法。
摘要由CSDN通过智能技术生成

指针: 存储值的地址变量

初始化指针

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

constint*后面, 意味着不可以修改指针的指向, 表明pconst

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;
}
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值