C语言:高级——指针基础

目录

前言

一、指针的介绍

二、段错误(Segment fault)

三、指针运算

四、函数传参

五、数组传参

六、二级指针

七、常量指针和指针常量


前言

指针编程是C语言的灵魂,通过指针对数组字符串、函数参数、内存地址进行操作,可以使程序更简洁,工作事半功倍。说白了,玩C语言关键就在于玩指针。

一、指针的介绍

指针的定义和初始化示例如下:

/*指针定义:
* 类型说明符 *指针变量名;
* 类型说明符表示指针指向的变量的数据类型,*为指针运算符
* 指针变量只能存放地址类型数据,且只能指向同一种数据类型
*/

int *p1; // 未初始化(野指针:指向一个不确定的内存区域)

char *p2 = NULL; // 初始化为NULL(空指针:目前并未指向任何位置)

float data = 3.14f;
float *p3 = &data; // 初始化为变量的地址,&为取址运算符

printf("data:%f", data); // 直接访问
printf("data:%f", *p3); // 间接访问

printf("&data:%p", &data); // 打印变量地址
printf("&data:%p", p3);

二、段错误(Segment fault)

在编译完程序执行时,有时会莫名出现“Segment fault”提示,通常是指访问的内存超出了系统分配给这个程序的内存空间。常见原因如下:
1、操作空指针
2、操作地址不存在的内存
3、操作受系统保护的内存
4、修改常量区中的内容

/*操作空指针可能会出现段错误*/
int *p1 = NULL;
printf("*p1:%d\n", *p1);

/*操作野指针可能会出现段错误*/
int *p2;
printf("*p2:%d\n", *p2);
*p2 = 100;

/*指针指向一个错误的内存地址可能会出现段错误*/
int *p3 = (int*)0x123ef;
printf("*p3:%d\n", *p3);

常见避免方式:
1、变量、数值、指针等均要做初始化
2、数值不要越界操作
3、通过指针不要随意去操作不存在或受系统保护的内存

常见解决方式:
1、通过不断地注释代码来缩小段错误出现的范围
2、利用GDB调试器来查找段错误
3、通过学习前人的经验和开发的工具

三、指针运算

/*运算符*/
// 两个表达式等价,指针运算符*是取址运算符&的反运算符
a = 10;
*(&a) = 10;

/*赋值运算*/
// 指针赋值实际上是地址的复制
// 左值代表存储单元,右值代表存储内容
int a = 10;
int *p1 = &a;
int *p2;
p2 = p1; // p1和p2指向同一变量a

/*加减运算*/
int a[] = {1, 2, 3, 4, 5};
int *p = a; // 指向数组的指针,数组名是数组首元素的地址
p = p + i; // 指向当前元素后第i个元素
p = p - i; // 指向当前元素前第i个元素

/*比较运算*/
// 前提是两个指针都指向一个数组中的元素,不同内存区域的指针比较没有意义
p_a < p_b; // 如果a存储在b的前面,则返回true
p_a <= p_b; // 如果a存储在b的前面或两个指针指向同一位置,则返回true
p_a == p_b; // 如果两个指针指向同一位置,则返回true
p_a != p_b; // 如果两个指针指向不同位置,则返回true
p_a == NULL; // 如果a是空值,则返回true

/*指针相减*/
// *(a + i)(指针法)等价于a[i](下标法)
int a[] = {1, 2, 3, 4, 5};
int *p1 = a;
int *p2 = a + 4;
printf("%d", p2 - p1); // 打印两个元素之间相差的存储单元个数

四、函数传参

1、值传递

数据传送是单向的,只能把实参传递给形参,形参的变化不会影响实参。

2、地址传递(指针传递)

形参指针的变化不会影响实参指针,但可以通过形参指针修改实参指针所指向的存储单元中的值。

void swap (int *p1, int *p2) // 交换两个整数
{
    int temp;
    temp = *p1;
    *p1 = *p2;
    *p2 = temp;
}

五、数组传参

实参形参
数组名数组名
指针数组名
数组名指针
指针指针

六、二级指针

二级指针也称为指针的指针,指向另一个指针变量。

int a = 10; // 变量
int *p = &a; // 一级指针
int **pp = &p; // 二级指针

七、常量指针和指针常量

1、常量指针

常量指针本身可以被修改,它所指向的存储单元的值不可以修改。通过其他指针可以修改常量指针所指向的存储单元的值。常量指针通常作为函数的形参使用。

类型说明符 const *指针变量;

2、指针常量

指针常量本身不可以被修改,它所指向的存储单元的值可以修改。通过二级指针可以修改指针常量本身。

类型说明符 * const 指针变量;
wAAACH5BAEKAAAALAAAAAABAAEAAAICRAEAOw==

3、指向常量的指针常量 

指针本身不可以被修改,它所指向的存储单元的值不可以修改。通过其他指针可以修改指针本身,也可以修改指针所指向的存储单元的值。

类型说明符 const * const 指针变量;
wAAACH5BAEKAAAALAAAAAABAAEAAAICRAEAOw==
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值