跳转至

指针

一、指针的重要性

  1. 表示一些复杂的数据结构
  2. 快速的传递数据,减少了内存的消耗
  3. 使函数返回一个以上的值
  4. 能直接访问硬件
  5. 能够方便的处理字符串
  6. 是理解面向对象语言中引用的基础
  7. 指针是C语言的灵魂

二、指针的定义

1. 地址

  1. 内存单元的编号
  2. 从0开始的非负整数

2. 指针

  1. 指针就是地址,地址就是指针
  2. 指针变量就是存放内存单元编号的变量,或者说指针变量就是存放地址的变量
  3. 指针和指针变量的两个不同的概念
  4. 通常我们叙述时会把指针变量简称为指针,实际它们含义并不一样
  5. 指针的本质就是一个操作受限的非负整数

三、指针的分类

1. 基本类型指针

1
2
3
4
5
6
7
8
9
#include <stdio.h>
int main(int argc, char const *argv[])
{
    int *p;
    int i = 3;
    p = &i;
    printf("%p\n", p);  // 0x7ffff3688088
    return 0;
}

1. 指针的理解

1
int *p;
  1. p是变量的名字,int *表示p变量存放的是int类型变量的地址

  2. int *p;不表示定义了一个名字叫做*p的变量

  3. 应该这样理解:p是变量名,p变量的数据类型是int *类型,所谓int *类型,实际就是存放int变量地址的类型
1
p = &i;
  1. p保存了i的地址,因此p指向i
  2. p不是i,i也不是p,更准确的说:修改p的值不影响i的值,修改i的值也不会影响p的值
    1. 如果一个指针变量指向了某个普通变量,则*指针变量就完全等同于普通变量,例如此处*p就完全等同于i

*的含义:

  1. 乘法
  2. 定义指针变量
  3. 指针运算符,该运算符放在已经定义好的指针变量前面,如果p是一个已经定义好的指针变量,则*p表示以p的内容为地址的变量。

2. 指针常见错误

错误1:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
#include <stdio.h>
int main(int argc, char const *argv[])
{
    int *p;
    int i = 5;
    *p = i;
    printf("%d\n", *p);
    return 0;
}
// 运行错误Segmentation fault (core dumped)

错误2:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
#include <stdio.h>
int main(int argc, char const *argv[])
{
    int *p;
    int *q;
    int i = 5;
    p = &i;
    *q = p;  // 语法错误
    printf("%d\n", *q);
    return 0;
}

3. 指针变量的运算

  1. 指针变量不能相加、不能相乘、不能相除
  2. 如果两个指针变量指向的是同一块连续空间中的不同存储单元,则这两个指针变量才可以相减。

4. 指针经典程序-互换两个数字

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
#include <stdio.h>
void swap(int *p, int *q)
{
    int t;
    t = *p;
    *p = *q;
    *q = t;
}
int main(int argc, char const *argv[])
{
    int a = 3;
    int b = 5;
    swap(&a, &b);
    printf("a = %d, b = %d\n", a, b);
    return 0;
}

2. 指针和数组

2.1 指针和一维数组

1. 指针和数组名

一维数组名是个指针常量,它存放的是一维数组第一个元素的地址

2. 指针和下标

如果p是个指针变量,则p[i]永远等价于*(p+i)

3. 函数处理数组

如果函数要处理一个一维数组,则需要接收该数组的2个信息:

  1. 数组第一个元素的地址
  2. 数组的长度

3. 指针和函数

4. 指针和结构体

5. 多级指针

1
2
3
4
int i = 10; 
int *p = &i;  // p只能存放int类型变量的地址
int **q = &p;  // q是int **类型,p只能存放int *类型变量的地址
int ***r = &q;  // r是int ***类型,r只能存放int **类型变量的地址