(C语言)指针初识(1)——指针概念及指针类型

        指针,看似是一个令人头疼的问题,静下心来慢慢学习。指针这个主题,分成了几个的板块,比较多,耐心看完,一定会有收获啦!慢慢来,总是需要一个循序渐进的过程。

目录

一、什么是指针

二、指针和指针类型

指针类型的意义:

结论1:

结论2:


一、什么是指针

        把指针想象成是一个房间号,简单的想一下,在一个风和日丽的早晨,你去了一家偌大的宾馆,你第一次去,找不到对应的房间,而那些房间从外面看起来,真的就是一摸一样。而这个时候,你该怎么办呢?宾馆的房间号在这时候是不是就起作用了。

        而内存呢,也是类似于这样的,将内存空间切割为一个个小的内存单元,并对其进行编号。其编号就是地址,也称为指针。

1、指针就是地址,是内存中一个最小单元的编号

2、口语中的指针其实指的是指针变量,是用来存放内存地址的变量

3、指针变量里面存放的是地址,而通过这个地址,就可以找到一个内存单元

4、指针的大小:在32位平台是4个字节,64位平台是8个字节(x86-->32位环境,x64-->64位环境)

理解过程:内存空间是如何管理的?

(1)、切割成内存单元,每个内存单元为1个byte(字节)

(2)、给每个内存单元进行编号(编号的意义:能够快速找到指定的内存单元),把内存单元的编号称为地址

(3)、指针就是地址,地址就是编号,即:指针就是内存单元的编号

分析如下代码:

#include<stdio.h>
int main()
{
	int a = 0;
	int* p = &a;
	return 0;
}

上述代码的理解:

(1)、a是整型变量,占用4个字节的内存空间,如图:

注:(A、内存单元的编号,是当程序执行时,直接有硬件生成的,所以每一次运行,其编号都是不一样的。

       (B、&a——就是通过取地址操作操作符,取出a的地址,所以,&a就是代表a的编号,即:&a就是a的地址

(2)、int* p=a;

p是一个指针变量,用来存放地址的(用来存放指针的),而通过这个地址,就可以找到相应的一个内存单元。

注:再次强调,口语中会说,p就是一个指针,实际上指的是p是一个指针变量,而指针变量就是一个变量,用来存放地址的一个变量。

分析如下代码:

int main()
{
	int* p = NULL;
	char* l = NULL;
	double* d = NULL;
	//printf("%d\n", sizeof(p));
	//printf("%d\n", sizeof(int*));
	//printf("%d\n", sizeof(char*));
	//printf("%d\n", sizeof(double*));

	printf("%zu\n", sizeof(p));
	printf("%zu\n", sizeof(int*));
	printf("%zuh\n", sizeof(char*));
	printf("%zu\n", sizeof(double*));
	return 0;
}

        我这里用的在x64的环境下,所以输出都是8。在这里有一个小小的细节,我们没有使用%d的形式打印,而是zu,原因:sizeof返回值的类型为无符号整型-->unsigned int---->所以上面用%d打印会有警告。在这里也再次验证了,指针的大小只与平台有关。

二、指针和指针类型

指针类型的意义:

结合下面代码分析:

代码1:

#include<stdio.h>
int main()
{
	int a = 0x11223344;
	int* pa = &a;
	*pa = 0;//改变了4个字节
	printf("%d\n", *pa);
	
	
	return 0;
}

分析:

1、0x开头的是十六进制数,两个十六进制数代表一个字节,因为一个十六进制位能翻译为4个二进制位,2个就是8个二进制位,8个二进制数就是一个字节,因此2个十六进制数对应1个字节。

2、存放0x11223344需要4个字节,而int a刚好就是4个字节的空间。在调试中,去内存里面查看&a,就可以观察到,已经存放进去了,至于为什么是倒着存进去的,这里先不深究。

 3、当调试走到*pa=0;时观察内存&a的值就变成了如下:

 是将4个字节都改变成了00

代码2:

#include<stdio.h>
int main()
{
    int a=0x11223344;
    char* pc1 = &a;//int* 和char* 类型不兼容
	char* pc = (char*)&a;//所以在这里要进行强制类型转换
	*pa = 0;//只改变了一个字节,因为是char* 类型的
	printf("%d\n", *pc);
    return 0;
}

分析:

1、在调试中,去内存里面查看&a,就可以观察到,已经存放进去了。(每次程序运行时,分配的地址都是随机的,所以这里的&a的地址编码和代码1中的编码不同)

 2、char*是可以存放int*的地址,差异在于取出使用时会有差异

3、当调试走到*pa=0后,在走一步,会发现如下结果:

在这里只改变了第一个字节的值

结论1:

结合代码1、2,我们发现,指针变量类型的不同不会影响指针所占空间的大小。

指针类型决定了指针在被解引用的时候访问几个字节。

如果是int*的指针,解引用访问4个字节

如果是char*的指针,解引用访问1个字节

推广:

如果是double*的指针,解引用访问8个字节

代码2:

#include<stdio.h>
int main()
{
	int a = 0x11223344;
	int* pa = &a;
	char* pc = (char*)&a;

	printf("pa  =%p\n", pa);
	printf("pc  =%p\n", pc);

	printf("\npa  =%p\n", pa);
	printf("pa+1=%p\n", pa + 1);

	printf("\npc  =%p\n", pc);
	printf("pc+1=%p\n", pc + 1);

	return 0;
}

运行结果:

 分析:

1、char*是可以存放int*的地址的

2、计算pa+1是加了4个字节,而计算pc+1时,加了1个字节

结论2:

指针的类型决定了指针+-1操作时,跳过几个字节

决定了指针的步长

误区:

虽然float*和int*的权限看似一样,但并不意味着 float*和 int*能通用

因为不同的类型,看待数据的视角不同。int* 看待的是整型的数据,而float*看待的是浮点型的数据。例:

代码:

int main()
{
	int a = 0;

	int* pi = &a;//pi解引用访问4个字节,pi+1也是跳过4个字节
	float* pf = &a;//pf解引用访问4个字节,pf+1也是跳过4个字节

	*pi = 100;

	return 0;
}

打开调试,查看内存中&a,如下:

 100的十六进制就是64

代码:

int main()
{
	int a = 0;

	int* pi = &a;//pi解引用访问4个字节,pi+1也是跳过4个字节
	float* pf = &a;//pf解引用访问4个字节,pf+1也是跳过4个字节

	//*pi = 100;
	*pf = 100;

	return 0;
}

打开调试,查看内存中&a,如下:

int*以整型数据存储方式去存储的 , float* 是以浮点数据存储方式去存储的 ,二者在存储时其规则是不同的,所以存储时的值会有差异,所以,二者是不能混用的。

指针这个主题会持续更新的喔,慢慢看。

如有不对的地方,还望大佬指出!

  • 15
    点赞
  • 54
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 2
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

龙洋静

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值