C语言 -指针

一、一级指针

1.1 基本结构

一级指针变量名:存储普通变量的地址

指针:指针就是地址

指针变量:用于存放地址的变量

格式:存储类型 数据类型 *指针变量名           int *p

  • 数组名也是变量的首地址,是地址常量,不能为左值(=左边),不能被重新赋值。
  • p 和 a不同的是,p是指针变量,而 a是个常量,所以可以用等号给 p赋值,但是不能给 a赋值,

int a=5;

int *p=&a; // a的地址赋给指针p,p里面储存的是a的地址

a 与 *p 输出值一样,都是变量的值;&a 与 p 输出值一样,都是地址。

如果在一行中定义多个指针变量,每个指针变量前面都需要加 * 来修饰,

1.2 指针操作符 

*:取地址里边的内容

&:取地址符: 取变量的地址

*&a:===  a

&*a:错误

 1.3 初始化

  • 指针在使用前要先定义,同时初始化,
  • 未初始化的指针变量不能随便使用,会产生野指针
  • 可以先定义一个空指针,后边可以重新赋值

  • 指针 p指向变量 a, *p可以访问到 a的值,
  • 可以通过 *p间接修改变量 a的值

  • 把数组的首地址赋值给指针变量

 

  • 将指针变量里面保存的地址赋值给另一个指针变量

 1.4 指针运算

1.4.1 算术运算

p++, p--

p++: 指针向高地址方向移动一个数据单位(int 4字节;char 1字节),指向下一个元素

指针的指向发生改变

单纯输出 p+1:暂时访问高地址,只是暂时访问,没有移动,实际指向的地址不变

同一个数组,两个地址之间的差值 = 相差元素个数 

1.4.2  关系运算

<      >       ==

  • 在同一个数组下
  • 相同类型的指针
  • 高地址 > 低地址(前面的指针 小于 后面的指针)

1.4.3 赋值运算

  • 同类型的指针可以相互赋值(void 除外)
  • 如果不同类型的指针想要相互赋值,必须进行强制类型转换

1.4.4 指针的大小

32位操作系统 ,指针大小为4字节 1字节==8位

8位 16进制 4*8=32位二进制 = 4字节

64位操作系统 ,指针大小为8字节

16位 16进制 4*16=64位二进制 = 8字节

 交换字符串,倒序输出

 

回文数判断

 

 输入字符,输出数字

 

1.5指针修饰

const 常量化 转换为只读

1.5.1 修饰普通变量

int const a = 5;

修饰普通变量,不能直接对变量名进行修改

可以通过指针进行修改,通过修改指针来间接修改变量

 1.5.2修饰指针 *p

int const *p = &a;

指针指向的内容不能修改;但是指针的指向可以修改

1.5.3 修饰 地址 p

int * const p=&a

指针的指向不能改,指针指向的内容可以改

const int *const p 既修饰指针指向的内容,又修饰指向,无法进行修改。 

二、二级指针

2.1 二级指针

一级指针存放普通变量的地址,二级指针存放一级指针的地址

格式:存储类型 数据类型 **指针变量名

int **p;

 三、指针和数组

3.1 指针和一维数组

数组名字取地址,变成 数组指针

一维数组名字 取地址,变成一维数组指针,加一即跳过一个一维数组 a[10]

a与 a+1 跳一个整形元素,a+1是 a[1]的地址,地址相差一个元素,四个字节

&a 就变成了一个一维数组指针,是 int (*p)[10] 类型

&a 与 &a +1 相差一个拥有十个元素的一维数组,地址相差40个字节

 3.2 访问

3.2.1 直接访问:通过数组名

  • 数组名也是变量的首地址,是地址常量,不能为左值(=左边),不能被重新赋值。
  • p 和 a不同的是,p是指针变量,而 a是个常量,所以可以用等号给 p赋值,但是不能给 a赋值,

地址

数组

元素

a

&a[0]

2

a[0]

*a

a+1

&a[1]

3

a[1]

*(a+1)

a+2

&a[2]

4

a[2]

*(a+2)

a+3

&a[3]

5

a[3]

*(a+3)

a+4

&a[4]

6

a[4]

*(a+4)

 3.2.2 间接访问:通过指针

地址

数组

元素

&p[0]

p

a

&a[0]

2

a[0]

*a

*p

p[0]

&p[1]

p+1

a+1

&a[1]

3

a[1]

*(a+1)

*(p+1)

p[1]

&p[2]

p+2

a+2

&a[2]

4

a[2]

*(a+2)

*(p+2)

p[2]

&p[3]

p+3

a+3

&a[3]

5

a[3]

*(a+3)

*(p+3)

p[3]

&p[4]

p+4

a+4

&a[4]

6

a[4]

*(a+4)

*(p+4)

p[4]

 

3.3 指针和二维数组

  • 一维数组的名字是数组的首地址,是的第一个元素的地址,是一个常量,数组名加 1表示下一个元素

二维数组的数组名表示第一行的首地址,数组名 加 1表示第二行的首地址

int a[2][3]={2,3,4,5}; // a:第一行的首地址 a+1:第二行的首地址

a是行地址,如果想访问其中的列(行地址和列地址级别不同,一行可以有多列),需要对他降级处理加 *

  • a: 第一行的首地址
  • a+1: 第二行的首地址
  • *a: 第一行第一列的地址

int a[2][3]={2,3,4,5,6,7};

  • printf("%p\n", a); //第一行的首地址
  • printf("%p\n", *a); //第一行第一列的地址
  • printf("%p\n", *a+1); //第一行第二列的地址
  • printf("%d\n", *(*a+1)); //取第一行第二列的内容

  • printf("%p\n", a+1); //第二行的首地址
  • printf("%p\n", *(a+1)); //第二行第一列的地址
  • printf("%p\n", *(a+1)+1); //第二行第二列的地址
  • printf("%d\n", *(*(a+1)+1)); //取第二行第二列的内容

地址

元素

a[0]

*a

a

2

a[0][0]

**a

*a[0]

a[0]+1

*a+1

3

a[0][1]

*(*a+1)

*(a[0]+1)

a[0]+2

*a+2

4

a[0][2]

*(*a+2)

*(a[0]+2)

a[1]

*(a+1)

a+1

5

a[1][0]

*(*(a+1))

*a[1]

a[1]+1

*(a+1)+1

6

a[1][1]

*(*(a+1)+1)

*(a[1]+1)

a[1]+2

*(a+1)+2

7

a[1][2]

*(*(a+1)+2)

*(a[1]+2)

 

3.4 数组指针

本质是指针,指向一个数组变量

格式:存储类型 数据类型 (*指针变量名)[列数]

p可以代替 a进行元素访问,但是本质不同

int a[2][3]={2,3,4,5,6,7};

int (*p)[3]=a;

地址

元素

p[0]

*p

a[0]

*a

a

2

a[0][0]

**a

*a[0]

p[0]+1

*p+1

a[0]+1

*a+1

3

a[0][1]

*(*a+1)

*(a[0]+1)

p[0]+2

*p+2

a[0]+2

*a+2

4

a[0][2]

*(*a+2)

*(a[0]+2)

p[1]

*(p+1)

a[1]

*(a+1)

a+1

5

a[1][0]

*(*(a+1))

*a[1]

p[1]+1

*(p+1)+1

a[1]+1

*(a+1)+1

6

a[1][1]

*(*(a+1)+1)

*(a[1]+1)

p[1]+2

*(p+1)+2

a[1]+2

*(a+1)+2

7

a[1][2]

*(*(a+1)+2)

*(a[1]+2)

 

 3.5 指针数组

指针和数组的关系:

  • 指针可以保存数组元素的 地址
  • 可以定义一个数组,数组中有若干相同类型的指针变量,这个数组被称为指针数组

概念:若干 相同类型的指针变量 构成的集合 本质是数组

定义:类型说明 * 数组名 [元素个数]

p :数组元素的地址,指针中元素的地址

p[ ] : 数组元素的内容(存放的是地址)

p[2] 与 *(p + 2) 是等价的,都表示指针数组中的第三个元素

p[2] 指针数组中的第三个元素

p 为数组名,为数组首地址,也是第一个元素的地址

p+2 为数组中第三个元素的地址,*(p+2) 为第三个地址的内容,也就是第三个元素的内容。

大小:sizeof(p)= 数组数据类型的单位元素大小 * 数组元素个数

int 类型指针数组,一个元素占 4 个字节 ,,char 类型指针数组,一个元素占 1 个字节

  • p[0] 为数组第一个元素,p 为数组名,为数组首地址
  • p[0] = &a; 把变量 a的地址赋给 p[0], p[0] 指向变量 a的地址,*p[0]为数组p[0] 指向的地址的值,也就是变量 a 的值。
  • b[2] 为数组 b的第三个元素,p[1] 为指针数组 p的第二个元素
  • p[1] = &b[2]; 数组 b的第三个元素的地址赋给 指针数组 p的第二个元素,p[1] 指向变量 b[2]的地址,*p[1] 是指向地址的变量值,也就是b[2]中变量的值。
  • p为指针数组名,为指针首地址,也是第一个元素的地址,p+1 为指针数组的第二个元素的地址,*(p+1) 位第二个地址存放的内容,也就是b[2]的地址,**(p+1)也就是第二个元素地址存放的内容的内容,也就是b[2]的内容

  • 字符串类型的指针数组中,元素储存的是字符串中首个字符的地址
  • 打印字符串 只需要找到字符串的首地址。
  • 在文字常量区开辟了一段空间存放字符串,
  • 将字符串的首地址赋给指针变量

指针数组 name中,第一个元素储存的是 hello中 h的地址,第二个元素储存的是 world中 w的地址

四、 运算方法

(1)* 和 ++ 都是单目运算符,优先级相同

(2)单目运算符从右向左运算

  • (*p)++:先算(*p)取内容,对内容++
  • *p++:先算p++,由于++在后,对p取*,最后再 p++
  • *(p++) :同上
  • ++*p :先算*p得到内容,再去 ++内容
  • ++(*p):同上
  • *++p :先算++p, 由于++在前,p先自加,对自加后的地址取内容
  • *(++p) :同上
  • 17
    点赞
  • 30
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
C语言是一种广泛应用于系统编程和嵌入式开发的高级编程语言。函数指针C语言中的一个重要概念,它可以指向函数,并且可以通过函数指针来调用函数。快速排序算法是一种常用的排序算法,它的核心思想是通过分治的策略将一个大问题分解为多个小问题,并通过递归的方式解决这些小问题。 下面是C语言中使用函数指针实现快速排序算法的示例代码: ```c #include <stdio.h> // 交换两个元素的值 void swap(int* a, int* b) { int temp = *a; *a = *b; *b = temp; } // 快速排序的分区函数 int partition(int arr[], int low, int high) { int pivot = arr[high]; // 选取最后一个元素作为基准 int i = (low - 1); // 定义一个指针,用于指向小于基准的元素 for (int j = low; j <= high - 1; j++) { if (arr[j] < pivot) { i++; swap(&arr[i], &arr[j]); } } swap(&arr[i + 1], &arr[high]); return (i + 1); } // 快速排序函数 void quickSort(int arr[], int low, int high) { if (low < high) { int pi = partition(arr, low, high); // 将数组分区,并获取分区点的位置 quickSort(arr, low, pi - 1); // 对分区点左边的子数组进行快速排序 quickSort(arr, pi + 1, high); // 对分区点右边的子数组进行快速排序 } } // 打印数组元素 void printArray(int arr[], int size) { for (int i = 0; i < size; i++) { printf("%d ", arr[i]); } printf("\n"); } int main() { int arr[] = {10, 7, 8, 9, 1, 5}; int n = sizeof(arr) / sizeof(arr[0]); printf("原始数组:"); printArray(arr, n); quickSort(arr, 0, n - 1); printf("排序后的数组:"); printArray(arr, n); return 0; } ```

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值