C语言:指针1(变量指针和指针变量)

预备知识

内存地址

字节:字节是内存的容量单位,英文名byte,一个字节有8位,即1byte = 8bits

地址:系统为了便于区分每一个字节而对它们逐一进行的编号,称为内存地址,简称地址。int

a = 5;

基地址

单字节数据:对与单字节数据而言,其地址就是其字节编号。

多字节数据:对于多字节数据而言,其地址是其所有字节中编号最小的那个,称为基地址(首

地址)。

取址符

每个变量都是一块内存,都可以通过取址符 & 获取其地址。
int a = 100;
printf("整型变量 a的地址是:%p\n",&a);
int c = 'x';
printf("字符变量 c的地址是:%p\n",%c);// 地址采用12位16进制数表示

注意:

虽然不同的变量的尺寸是不同的,但是它们的地址的尺寸是一致的。

不同的地址虽然形式上看起来是一样的,但由于它们代表的内存尺寸和类型都不同,因此它

们在逻辑上是严格区分的。

变量指针与指针变量

变量指针与指针变量

指针概述

内存地址:系统为了内存管理的方便,将内存划分为一个个的内存单元(通常是1个字节),

并为每一个内存单元进行编号。内存单元的编号称之为该内单元的地址。一般情况下,我们每

一个变量都是由多个内存单元构成的,多以每个变量的内存地址,其实就是这个变量对应的第

一个内存单元的地址,也叫基地址/首地址。

变量指针

变量指针:变量地址称之为该变量的指针(本质是地址)。变量地址往往是指变量在内存中第

一个内存单元的编号(首地址)
int a;
&a --- 变量a的地址,也称为变量a的的指针
int arr[2];
&arr --- 数组arr的地址,也称为数组arr的指针

指针就是地址,地址就是指针

指针变量:专门存放指针的变量(本质是变量),简单来说,用来存放地址的变量就是指针变

量。

指向:指针变量中存放 谁 的地址,就说明该指针变量指向了 谁

指针的尺寸

指针的尺寸指的是指针所占内存的字节数

指针所占内存,取决于地址的长度,而地址的长度则取决于系统寻址范围,即字长

结论:指针尺寸只跟系统的字长有关系,根具体的指针的类型无关。

小贴士:

Linux系统中打印地址时,最多显示12个十六进制数,为什么?

Linux64位操作系统中,一个内存地址占8个字节,一个字节8bit位,所以一个地址

8*8=64bit位, 每4个bit可以表示1个十六进制数; 64个bit位用十六进制表示最多有16个数值

位;

系统为了寻址方便,默认当前计算机系统没必要寻址64bit为,只寻址了48个bit为,所以用

12个十六进制数表示一个地址

二进制:

0100 1010 十六进制: 0x4A 4*16+10 = 74

注意: 在Linux64位操作系统中,指针类型的变量占8个字节的内存空间 在Linux32位操作

系统中,指针类型的变量占4个字节的内存空间。

在C语言中对内存数据(如变量、数组元素等)的存取有两种方式:

直接存取:

通过基本类型(整型、浮点型、字符型)的变量,访问这个变量代表的内存空间的数据

通过数组元素的引用,访问这个引用代表的内存空间的数据。

int a = 10;// 存

printf("%d",a);// 取

int arr[] = {11,22,33}; // 存

arr[0] = 66;// 存

printf("%d",arr[0]);// 取

间接存取:

通过指针变量,间接的访问内容中的数据。

* :读作解引用,是解引用符号。如果 * 前有数据类型,读作指针;如果 * 前没有数据类

型,读作解引用

案例:
#include <stdio.h>
int main(int argc,char *argv[])
{
// 定义一个普通变量
int i = 3;
// 定义一个指针变量,并赋值
int *i_point = &i; // 指针变量的数据类型要和存储的地址变量类型一致
// 访问普通变量(直接访问)
printf("直接访问-%d\n",i);
// 访问指针(地址访问)%p访问地址
printf("地址访问-%p,%p\n",&i,i_point);
// 访问指针变量(间接访问)解引用:通过这个指针变量存储的地址,访问这个地址对应空间的数据
printf("间接访问-%d\n",*i_point); // 3
// i_point(地址)和 *i_point(数据)
}

指针变量的定义

语法:数据类型 *变量列表;

注意:

1. 虽然定义指针变量 *a ,是在变量名前加上 * ,但是实际变量名依然为 a ,而不是 *a ;

2. 使用指针变量间接访问内存数据时,指针变量必须要有明确的指向;

3. 如果想要借助指针变量间接访问指针变量保存的内存地址上的数据,可以使用指针变量前加 *

来间接返访问。

指针变量前加 * ,我们称之为对指针变量 解引用
int i = 5, *p;
p = &i;// 将i的地址赋值给指针变量p
printf("%x,%p\n",p,p);// 两个都是打印地址,%x打印的地址不带0x,%p打印的地址带0x
printf("%d\n",*p);// 间接访问i的值,也称为解引用p对应地址空间的值。
*p = 10;// p访问地址,*p访问地址空间对应的数据

4. 指针变量只能指向同类型的变量,借助指针变量访问内存,一次访问的内存大小是取决于指针

变量的类型。

5. 指针变量在定义时可以初始化:这一点和普通变量是一样的。
int i = 5;
int *p = &i; // 将i的地址赋值给指针变量p
printf("%d\n",*p);

指针变量的使用

使用

指针变量的赋值
// 方式1
int a, *p;
p = &a; // 指针变量的值是其他变量的地址
// 方式2
int a,*p,*q = &a;
p = q;

操作指针变量的值

int a,*p,*q=&a;
p = q;
printf("%p",p);// 此时返回的是变量a的地址空间
操作指针变量指向的值
int a = 6,*q = &a,b = 25;
*q = 10;
printf("%d,%d",*q,a);// 10,10
q = &b;
// *q = 15;
printf("%d,%d",*q,a);// 25,10

两个有关运算符的使用

& 取地址运算符。&a是变量a的地址。

* 指针运算符(或称之为“间接访问”运算符,解引用符),*p是指针变量p指向的对象的值。

指针变量做函数参数

指针变量做函数参数往往传递的是变量的地址(首地址),借助与指针变量间接访问是可以修改实

参变量数据的。

案例1

需求:要求函数处理,用指针变量做函数的参数

方式1:交换指向(指向的普通变量的值不变)
#include <stdio.h>
// 自定义一个函数,实现两个数的比较
void swap(int *p_a,int *p_b)
{
int *p_t;
// 这种写法,只会改变指向,不会改变地址对应空间的数据
p_t = p_a;
p_a = p_b;
p_b = p_t;
printf("%d > %d\n",*p_a,*p_b);
}
void main()
{
int a = 3, b = 5;
// int *p_a = &a, *p_b = &b;
// if(a < b) swap(p_a,p_b);
if(a < b)
swap(&a,&b);
else
printf("%d > %d\n",a,b);
}
方式2:交换数据(指向的普通变量的值改变)
#include <stdio.h>
// 自定义一个函数,实现两个数的比较
void swap(int *p_a,int *p_b)
{
int t;
// 这种写法,改变的是指针指向地址空间的数据
t = *p_a;
*p_a = *p_b;
*p_b = t;
printf("%d > %d\n",*p_a,*p_b);
}
void main()
{
int a = 3, b = 5;
// int *p_a = &a, *p_b = &b;
// if(a < b) swap(p_a,p_b);
if(a < b)
swap(&a,&b);
else
printf("%d > %d\n",a,b);
}

指针变量指向数组

数组元素的指针

数组的指针就是数组中的第一个元素的地址,也就是数组的首地址。

数组元素的指针是指数组的首地址。因此,同样可以用指针变量来指向数组或数组元素。

在C语言中,由于数组名代表数组的首地址,因此,数组名实际上也是指针。
#include <stdio.h>
int main(int argc,char *argv[])
{
int a[] = {11,22,33};
int *p1 = &a[0];// 数组的首地址
int *p2 = a; // 数组的首地址
printf("%p,%p,%p\n",p1,p2,a);// 0x7ffd99911850,0x7ffd99911850,0x7ffd99911850
return 0;
}

注意:虽然我们定义了一个指针变量接收了数组地址,但不能理解为指针变量指向了数组,而应该

理解为指向了数组的元素。

指针的运算

指针运算:指针变量必须要指向数组的某个元素

说明:

① 如果指针变量p已指向数组中的一个元素,则p+1指向同一数组中的 下一个元素,p-1指向

同一数组中的上一个元素。即p+1或p-1也表示地址。但要注意的是,虽然指针变量p中存放的

是地址,但p+1并不表示该地址加1,而表示在原地址的基础上加了该数据类型所占的字节数d

② 如果p原来指向a[0],执行++p后p的值改变了,在p的原值基础上加d,这样p就指向数组的

下一个元素a[1]。d是数组元素占的字节数。

③ 如果p的初值为&a[0]则p+i 和a+i 就是数组元素a[i]的地址,或者说,它们指向a数组的第 i

个元素 。

④ *(p+i) 或*(a+i)是p+i或a+i所指向的数组元素,即a[i]。

⑤ 如果指针变量p1和p2都指向同一数组,如执行p2-p1,结果是两个地址之差除以数组元素的

长度d。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值