【C语言指针专题(1)】简单了解指针

一、内存和地址

1.内存

在日常生活中,我们每个人都生活在某个省,一个省中有许许多多的人。

把人看成一串数据,那么这个省份就可以看作是一个内存,里面包括了许许多多的人(存储了许许多多的数据)。

计算机的CPU(中央处理器)在处理数据的时候,需要的数据是在内存中读取的,处理后的数据也会放回内存中。

那么很自然的,我们总会需要从内存中调取某个特定的数据,那么我们怎么高效的找到我们需要的这个数据呢?

其实就像日常生活中,我们用一个地址来找人一样。

我们说,张三住在A省B市CC小区102,这样就精确找到了张三。

而在计算机中,也有这么一个“地址”存在,它把很大一块内存划分成一个一个小单元(大小为1字节),每一个单元有一个唯一的“地址”,供我们来找到存在这个内存单元中的数据。

2.地址

2.1.地址到底是什么

计算机中的地址到底是怎么表示的呢?也是像现实生活中所说的,某省某市吗?让我们来实际看一看:

//演示1.2.1

#include <stdio.h>

int main()
{
	int a = 0;
	printf("%p\n", &a);    //%p表示以地址的形式打印,&是取地址操作符,&a意为取出a的地址
	return 0;
}

可以看到,计算机中的地址其实是一串十六进制数字。

为什么是这样一串数字呢?

2.2.地址的本质

其实在计算机中,给内存进⾏编址时,是通过硬件设计完成的。

⾸先,必须理解,计算机内是有很多的硬件单元,⽽硬件单元是要互相协同⼯作的。所谓的协同,⾄少相互之间要能够进⾏数据传递。

但是硬件与硬件之间是互相独⽴的,那么如何通信呢?答案很简单,⽤"线"连起来。 ⽽CPU和内存之间也是有⼤量的数据交互的,所以,两者必须也⽤线连起来。 不过,我们今天关⼼⼀组线,叫做地址总线。

我们可以简单理解,计算机中有许多地址总线, 每根地址线能表示一个0或1(电信号的无或有)。

这样每一根地址线表示出一个0或1,就形成了一个地址。通过这个地址,我们就可以找到某一特定的内存单元。

如此看来,计算机中的地址本质就是一串二进制数字。而我们在打印时,通常把它转换成十六进制打印,于是就有了演示1.2.1运行的结果,是一串十六进制数字。

二、指针变量

1.取地址操作符&

在演示1.2.1中,我们获取整型变量a的地址时,使用了&取地址操作符。

在C语言中,我们创建一个变量,其实就是在向内存申请一块空间,起名为a,来存放a中的数据。

既然这个变量向内存申请了一块空间,而每个内存单元都有唯一的地址,那么我们就可以通过地址来找到变量a所在的空间,&a就是在取出变量a的地址。

这里要注意,整型变量的大小是4个字节,而一个内存单元是1个字节。整型变量在内存上申请的空间是连续的,我们取出的a的地址,其实是这4个字节中地址相对较小的字节的地址。

2.指针变量 

2.1什么是指针变量

我们已经知道,通过&获取到的地址就是一串十六进制数字,其实也就是一个数据,那么自然而然地也可以像整型、字符、浮点数一样,通过创建一个变量,把这个数据存储到计算机中。

C语言中,创建的用于存储地址的变量,就叫做指针变量。

//演示2.2.1

#include <stdio.h>

int main()
{
    double a = 0.0;
    double* pa = &a;    //创建指针变量pa
    printf("%p\n", &a);
    printf("%p\n", pa);
    return 0;
}

可以看到变量a的地址很好的存放到了指针变量pa中。

2.2指针变量的类型

指针变量也有类型,它的类型就是它所指向的变量的类型再加上*。例如在演示2.2.1中,指针变量pa的类型是double* ;而如果在演示1.2.1中创建一个指针变量存放a的地址,那么这个指针变量的类型就是int* 。

总的来说,如果指针指向的变量a的类型是f,那么存放变量a地址的指针变量pa的类型就是f*,其中 * 表示pa是一个指针变量,f表示指针pa指向的变量a的类型是f。

在指针类型中有⼀种特殊的类型是 void* 类型的,可以理解为无具体类型的指针(或者叫泛型指 针),这种类型的指针可以用来接受任意类型地址。

3.解引用操作符 * 

3.1认识解引用操作符 *

上文中我们使用了符号 * 作为指针变量类型的一部分,表明接下来将要被声明的变量是一个指针。

除此之外,* 也可以单独使用,放在指针变量之前,这时候它就叫做解引用操作符,可以由指针变量中存放的地址,找到指针所指向的变量。

//演示2.3.1

#include <Stdio.h>

int main()
{
    short num = 13;
    short* pn = &num;
    printf("%d\n", num);
    printf("%d\n", *pn);
    return 0;
}

可以看到,通过解引用操作符 * 我们很好的找到了变量num的值并打印了出来。

3.2  * + 指针 的简单运用

解引用操作符作用于指针,其实就是通过指针变量中存放的地址,来找到这个地址所代表的一块内存空间,也就是被指向变量的空间。

那么就可以这么简单的理解,指针变量被解引用后,就相当于它所指向的那个变量。

那么就像我们可以对变量进行使用一样,我们也可以对经过解引用的指针变量进行使用。

//演示2.3.2

#include <stdio.h>

int main()
{
    int a = 3, b = 5;
    int* pa = &a, * pb = &b;

    printf("%d\n", *pa +1);
    printf("%d\n", *pa + *pb);
    return 0;
}

4.指针变量的大小

前⾯的内容我们了解到,机器中通过地址总线来对内存进行编码,每根地址线出来的电信号转换成数字信号后是1或者0,从而有了地址。

在32位机器(x86环境)中,有32根地址线,而在64位机器(x64环境)中,有64根地址线。

那我们把32根地址线产生的2进制序列当做⼀个地址,那么一个地址就是32个bit位,需要4个字节才能存储。 也就是说,如果指针变量是用来存放地址的,那么指针变量的大小就得是4个字节的空间才可以。

同理64位机器中,有64根地址线,⼀个地址就是64个⼆进制位组成的⼆进制序列,存储起来就需要8个字节的空间,指针变量的大小就是8个字节。

//演示2.4

#include <stdio.h>

int main()
{
    printf("%d\n", sizeof(int*));
    printf("%d\n", sizeof(short*));
    printf("%d\n", sizeof(long*));
    printf("%d\n", sizeof(float*));
    printf("%d\n", sizeof(char*));
    printf("%d\n", sizeof(double*));
    return 0;
}

x86环境下: 

x64环境下:

(不要管这里的绿色波浪线,我的代码没错)

注意指针变量的大小和类型是无关的,只要指针类型的变量,在相同的平台下,大小都是相同的。

  • 35
    点赞
  • 29
    收藏
    觉得还不错? 一键收藏
  • 4
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值