C语言-指针[变量指针与指针变量]
预备
内存地址
- 字节:字节是内存的容量单位,英文名Byte,1Byte = 8bit = 1Char
- 地址:系统为了便于区分每一个字节而对他们进行逐一编号(编号唯一),称之为内存地址,简称“地址”
基地址(首地址)
- 单字节数据:对于单字节数据,其地址就是其字节编号。char a = ‘A’
- 多字节数据:对于多字节数据,其地址就是所有字节中编号最小的那个,称为“基地址”,或者首地址
取地址符
-
每个变量都是一块内存,都可以通过取地址符
&
获取其地址(基地址) -
举例:
int a = 100;printf("整型变量a的地址:%p\n", &a);//0x~~ 64位系统下地址是一个12位的16进制整数,占8个字节//&a:获取变量a的首地址char c = 'x';printf("字符变量c的地址:%p\n",&c); //0x~~
- 注意:
- 虽然不同的变量的尺寸是不同的,但是他们的地址的尺寸是一致的
- 不同的地址虽然形式上看起来是一样的,但由于它们代表的内存尺寸和类型都不同,因此他们在逻辑上是需要严格区分
为什么引用指针
-
为函数修改实参提供支持
-
为动态内存管理提供支持
-
为动态数据结构(链表、队列、二叉搜索树)提供支持
-
为内存访问提供了另一种途径
变量指针和指针变量
指针的概念
内存单元和地址机制
- 内存单元划分
-
变量的存储特性
-
变量的基地址(首地址)是其首个内存单元的地址(首地址一般是这一组编号中最小的那个)
变量指针
- 本质:地址值(指针值),变量指针,其实就是变量的首地址。本质是地址
- 操作符:&(取地址符)
- 代码示例: &a(获取变量a的地址)
- 核心特性:不可修改(地址由系统分配)
指针变量
- 本质:存储地址的变量。本质是变量
- 操作符:==*(指针声明符,解引用符)==int *p
- 代码示例: int* p = &a;(存了变量a的地址)
- 核心特性:可修改指向(p = &b)
指向
指针变量中存放谁的地址,就说明该指针变量指向谁。
int a = 10;//变量a,存放常量10
int* p = &a;//指针变量p,存放变量a的地址,相当于。指针变量p指向对象aint b = 20;
p = &b;//指针变量p指向对象bdouble c = 12;
double* p1 = &c;
指针的尺寸
指针的本质
- 变量指针:数据的“门牌号”(&a)
- 指针变量:存储门牌号的“笔记本”(int *p;指针变量存储的地址所指向的对象类型是int类型,不能说指针变量是int类型)
- 指向操作:通过门牌号访问数据(*p)
int a = 10;
printf("%d\n",a); //直接访问对象a的值int *p = &a;
printf("%p\n", p); //直接访问只恨变量p的值,返回的是a的地址 p:访问指针变量,拿到的是地址值
printf("%d\n", p); //间接访问对象a的值,*p,解引用,访问p指向对象的数据 *p:访问指针变量指向的对象,拿到的对象的值
内存数据的存取方式
在c语言中对内存数据(变量、数组元素等)的存取有两种方式:
直接存取
-
通过基本类型(整型、浮点型、字符型)的变量,访问这个变量代表的内存空间的数据
-
通过数组元素的引用(下标),访问这个引用代表的内存空间数据
//基本 int a = 10; //存 printf("%d\n",a); //取//数组元素 int arr[] = {11,22,33}; //存 arr[0] = 66; //存 printf("%d\n",arr[0]); //取
间接访问
- 通过指针变量,间接的访问内存中的数据。
*
:指针声明符或解引用符。如果*
前面有数据类型,读作声明指针
#include <stdio.h>
int main()
{//定义一个普通变量int a = 3;//定义一个指针变量,并赋值(指针变量本身还是一个变量,只不过只能存放地址值)int *p = &a; //这里的地址值一定要有其在内存中对应的空间//访问变量aprintf("%d\n",a);//直接访问printf("%d\n",*p);//间接访问return 0;
}
指针变量的定义
语法:
//1
数据类型 *变量列表;//2
数据类型* 变量;
举例:
int a;//普通变量
//指针变量
int *p1; //p1是指针变量
int* p4; //p4是指针变量int *p2,*p3; //p2,p3是指针变量int* p5,p6; //p5是指针变量,p6是普通变量
int *p7,p8; //p7是指针变量,p8是普通变量
指针变量的值只能是8(32位系统)| 12(64位系统)位的十六进制数
④指针变量只能指向同类型变量,借助指针变量访问内存,一次访问的内存大小是取决于指针变量的类型
int a = 10;
double b = 10;int *pa = &a; //指针的类型 要和指向对象的 类型一致
double *pb = &b;//这里的double不是指针的类型,是指针指向的对象的类型
printf("%d\n",a);
⑤指针变量在定义时可以初始化,这一点和普通变量一致。(指针变量本质上还是变量,只不过存放的是地址)
int a = 5;
int *p = &a; //定义变量的同时初始化
printf("%d\n",*p); //5int b;
int *p1 = &b;
printf("%d\n",*p1); //随机值
指针变量的使用
- 指针变量的赋值
//1
int a, *p;
p = &a; //先定义后附值//2
int a1, *p1, *q1 = &a1;
p1 = q1; //变量的赋值,将q1的值赋值给p1。q1和p1都指向a1,都能修改a1
- 操作指针变量的值
int a, *p, *q = &a;
p = q; //变量的赋值,将q的值赋值给p。q和p都指向a,都能修改a
printf("%d\n",*p1); //访问p的值也就是a的地址
- 操作指针变量指向的值
int a = 5, *q = &a,b = 25;
*q = 10;//赋值操作,修改q指向a的值, a = 10
printf("%d,%d\n",*q,a); //10,10q = &b; //赋值操作,给指针变量q重新赋值,此时q指向b
printf("%d,%d\n",*q,a); //25,10
指针运算符的使用
- &:取地址运算符。&a是获取变量a的地址值。这个是变量指针
- *****:指针运算符、间接访问运算符,*p是指针变量p指向的对象的值,这个是指针变量
案例1
- 通过指针变量访问整型变量