【C语言】带你层层深入指针——指针详解1

前言:
本期开始详解指针,由于文章过长,所以分了几篇文
若内容对大家有所帮助,可以收藏慢慢看,感谢大家支持
谢谢大家 ! ! !

一、地址是什么?

引子:

我们将内存比作宿舍楼,内存单元比作房间,地址比作房间号。
若在100个无房间编号中找人需要逐个查找,效率极低。
给房间编号后(如101、201),通过编号可快速定位。
而计算机中也是如此,原理与此相同
通过内存地址快速访问数据

我们可以打印出地址来一探究竟:
用%p来打印地址
用&取地址操作符来拿到地址

#include <stdio.h>

int main()
{
	int a = 20;
	printf("%p\n\n", &a);
	//%p用于打印地址
	//&a可拿到a的地址

	return 0;
}

运行结果:
(我们这里使用x86环境,方便观察地址)
(打印的地址是十六进制)
在这里插入图片描述

二、指针变量

1.指针是什么?

  • 地址作用:
    就像宿舍地址可以找到具体的人一样,内存地址用于定位变量在内存中的位置
  • 指针本质:
    指针变量存储的是其他变量的内存地址,相当于"保存地址信息的容器"
  • 操作流程:
    先获取变量地址存入指针,再通过指针找到原变量("一来一回"的过程)

内存单元的编号=地址=指针
在C语言中,给地址起名-——指针

2.指针变量定义

int * pa = &a;

此处 ” pa “ 是一个变量,用来存放地址(指针),是指针变量
int * 是指针变量的类型
“ * ” 表示pa是指针变量,而int 表示pa指向的变量a类型是int

3. 取地址与解引用

  • 取地址操作符(&):
    获取变量的内存地址,如&a表示变量a的地址
  • 解引用操作符(*):
    通过指针访问指向的变量,如*pa表示访问pa指针指向的值
  • 操作示例:
int a = 20;
int * pa = &a;
*pa = 200;
//通过地址找到a 并将a的值改为200
  • 互相抵消:
    *(&a)等价于直接访问a本身,两个操作符可以相互抵消

三、指针变量相关计算

1.指针变量大小

** 指针变量在内存中占用的空间大小**

在32位操作系统中
地址是32个bit位,指针变量大小是4个字节
而在64位操作系统中
地址是64个bit位,指针变量大小是8个字节
( 1字节 = 8bit位 )
所以,指针变量的大小和类型是无关的,只要是在相同平台下,所有指针类型的变量大小都是相同的

但是:
指针类型决定了指针进行解引用时的访问权限大小

  • 示例1:
    int * 类型指针解引用可访问4个字节
    (如 *p = 0 会将4字节全置零)
  • 示例2:
    char * 类型指针解引用仅访问1个字节
    (如 *p = 0 只修改首字节为零)

2.指针加减整数

指针类型决定指针加减整数时的步进距离
( +1 / -1 时走的距离)

int * 指针加 1 跳过 4 个字节
(如 p + 1 从 0xA8 变为 0xAC )
char * 指针加 1 跳过 1 个字节
(如 p + 1 从 0xA8 变为 0xA9 )

代码演示:

#include <stdio.h>

int main()
{
	int a = 20;
	int* pa1 = &a;
	//int* 类型指针
	char* pa2 = &a;
	//char* 类型指针

	printf("%p\n", &a);
	printf("%p\n", pa1);
	printf("%p\n", pa2);
	printf("%p\n", &a + 1);
	printf("%p\n", pa1 + 1);
	printf("%p\n", pa2 + 1);

	return 0;
}

运行结果:
在这里插入图片描述
可以见得:

  • int * 指针加 1 跳过 4 个字节
  • char * 指针加 1 跳过 1 个字节

特别注意:

void * 指针不能计算!!!
void * 是无具体类型的指针,可以用于接受任意类型地址
但是,void * 类型指针不能直接进行指针 + - 整数和解引用的运算
仅作为地址的临时存储容器
实际使用前需强制转换为具体类型指针

3.指针间的运算

指针之间的运算就好比时间日期的运算,只能相减不能相加
指针相减得到两个指针之间的元素个数(绝对值)
结果可能为正或负,取决于指针地址高低关系

且注意:
两指针必须指向同一块连续内存空间(如数组)
不同类型指针相减无意义(如char减int

代码演示:

#include <stdio.h>

int main()
{
	int arr[20] = { 0 };

	int* p1 = &arr[0];
	//将arr[0]的地址赋给p1
	int* p2 = &arr[19];
	//将arr[19]地址付给p2

	printf("%d\n\n", p1 - p2);

	return 0;
}

运行结果:

在这里插入图片描述

每个字节都有地址,地址本身具有大小关系
随着数组下标的增长,地址由低到高变化

所以,指针之间可以比较大小
可以比较两个指针变量存储的地址值,或指针与数组边界地址的关系来比较大小

结语

本期资料来自于:在这里插入图片描述

https://legacy.cplusplus.com/

OK,本期的指针详解到这里就结束了
由于文章过长,所以分了几篇文
若内容对大家有所帮助,可以收藏慢慢看,感谢大家支持

本文有若有不足之处,希望各位兄弟们能给出宝贵的意见。谢谢大家!!!
新人,本期制作不易希望各位兄弟们能动动小手,三连走一走!!!
支持一下(三连必回QwQ)

评论 35
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值