<c语言指针> 指针--c语言的精华

        刚接触指针的时候,感觉指针也就那样,不就是记录个地址吗,有什么难的,这个代表存储位置的东西能玩出什么花来?

        后来,因为数据结构的学习,才理解指针的nb。这玩意的厉害,不是通过描述来知道有多好用,而是随着自己的学习深入慢慢感受到的。伟大的东西总是简洁的。

        指针理解

        往上来说,使用指针可以做很多事,随着计算机的学习会解锁更多的指针相关的技能点,除非说是复习,直接通过一个文章或者一个视频直接掌握指针使用都是不现实的,这玩意需要多用才能感悟。 往下来说,理解计算机如何通过地址访问数据,可以让学习者在使用指针时有更好的体会和理解。

        学习指针会有的困惑:

        我在刚接触指针的时候,有很多关于地址这个概念的疑惑。

        比如,关于占用内存的疑惑:指针是个地址,那地址是需要存储的,既然地址被存储了,那存放地址的地址必然是像其他数据一样被存在了某个地方,同样,地址的地址的地址也得有地方存,所以得有地址的地址的地址的地址。。。这样无限套娃下去。让人很难想象,我们可以通过地址找东西,但谁来找地址?

        

        再还有,地址像大楼的门牌号,哪怕是个空的楼房,这个门牌号都是在的,也是占位置的,

但是我们发现,计算机的内存似乎可以是空的,难道是门牌号占用的内存没有被算到?

         当我们需要找到一个楼的某一个房间,我们可以通过门牌号去找,但是,去找门牌也得有人去找啊,仅仅是知道门牌号,没有去找,也是没用的。计算机的指针也是,哪怕知道了地址,也总得有人去找才能访问,那么到底是谁带着这个地址去找我们想要的内容呢?

        我们是怎么通过“门牌号”找到“对应房间”的

        我们就以通过门牌号找房间来举例,首先,门牌号具有一个特征,那就是有规律且不重复,每个房间都有门牌号。且每一位都有具体的含义,如果门牌号是乱的或者是重复的或者是压根没号,那对于寻找房间还是没有帮助,和没有一样。

        所以,正常的门牌号不是一个单纯的数字,而是可以被解析器(人脑)解释,比如以下的小楼,看到这样的排列,我们的大脑(解析器)自然而然将以下的俩位数的第一位理解为楼层,第二位理解为普通的序号,当我们去找门牌32时,自然会忽略掉下面俩层,从第三层开始找。        

        那么对于计算机而言,指针变量也是类似的会被计算机解释理解为一种物理上的位置。

        其实,计算机不是什么路痴或者瞎子,他自己的三分地自己非常清楚,我们定义的指针变量只是给自己存下来的用的,就像我打电话问某人的微信号,我用纸笔记录了下来,这个记录并没有影响那个微信号的客观存在,仅仅是我多了一个可以用来找微信号的纸条。

        以下的p = &a 就是个“纸条”不管你有没有记下来他的地址,计算机自己都是知道a的地址的,

int a = 2;
printf("%d",a);
int a = 2;
int* p = &a;
printf("%d",*p);

        区别不过是打电话让A把B推荐过来还是打电话问A记下B的微信号去加,在你创建变量时,计算机自己就知道地址,(要不然取地址是怎么取到的);

        虽然从概念上讲存地址似乎可以无限递归,但在实际的计算机内存模型中,并没有无限制的“地址嵌套”。每一个指针变量都有自己的内存位置,用于存储一个有意义的地址值,而这个地址值指向的数据不再需要额外的地址来存储其自身的地址。我们可以直接通过指针访问内存中的数据,而不是需要不断寻找地址的地址。

        通过变量名就可以访问对应地址的内容了,为什么还需要有取地址访问?

        在源代码中,变量名是用来帮助程序员理解程序逻辑的一种符号标识。它们在编译阶段确实存在,并被编译器解析和处理。

        但在编译后的目标代码(如机器码或字节码)中,变量名通常不会直接存在。编译器会为每个变量分配存储空间,并生成指令来操作这些存储空间的地址,而不是变量名。换句话说,在编译后的代码,我们不再通过变量名来访问变量,而是通过内存地址

        在学习中,有时会遇到这样的代码,尤其是第一次遇到,会怀疑代码是否有问题:

char* p = "abcde";

        乍一眼看上去不对劲,怎么能把字符串赋值给指针p呢。

        理解一:"abcde"方便萌新程序员理解逻辑是通过字符数组char【6】 = “abcde”。数组本质是

字符指针,这样就圆回来了。

        理解二:c语言本身并没有也不需要有字符串类型的变量,只需要用字符指针+访问范围就够了,字符串的\0逻辑上就用来表示访问范围。就看解读方式是以字符解读还是以字符串解读。

        虽然没有这个常量字符串的变量名,但不代表计算机不知道他的实际地址。变量名只是方便人类理解逻辑。整形不能这么玩是因为会发生歧义:我们希望把常量2的地址存到指针变量a中,但实际成了初始化指针变量为2。

int* a = 2;

        计算机怎样通过一个地址确定要访问的字节数?

        例如:int*类型是c语言中的一个指针,指向的区域内容占用四个字节,那么在编译执行的时候,计算机怎么知道这个地址的内容占用四个字节。显然计算机偷偷的至少用一个东西来记录某个地址所指向的大小。

        在运行时,CPU并不直接“知道”某个地址的内容占用几个字节,而是依赖于指令集架构(ISA)提供的寻址模式和内存访问指令,结合编译器生成的代码来正确地存取数据。编译器在生成机器码时就已经将类型信息转化为特定长度的读写操作,从而保证能够正确处理不同类型的内存对象。

        至于指针类型名字,也不过是为了程序员方便理解代码逻辑(我觉得)。

        不管是int还是char存储起来都是机器码,之所以有各种含义,不过是解读方式问题:横看成岭侧成峰,远近高低各不同:

int a = 3
void* p = &a;
printf("%p",(int*)p);
printf("%c",(char*)p);
printf("%s",(char*)p);
printf("%f",(float*)p);

        以上证明指针变量不只是靠一串16进制数字找我们需要访问的东西。通过*(0x11223344)访问是错误的,指针变量的类型隐含着要访问多少字节,以及以何种方式解读访问的数据,对吗


        靠这个例子好像不能证明指针类型能做到用什么方式解读机器码,因为占位符已经完成了这一步。我们用一个别的办法,创建一个大小为4字节的字符数组,将他看做整形进行赋值操作,以检验指针类型是否在乎存的内容,或者说,“如何读数据”归不归指针类型管。

int main()
{
	char arr[4];
	int* a = (int*)(&arr);
	// 00000000 01000001 01000001 01000001等价 4,276,545(小端存储)
	*a = 4276545;
	printf("%s",arr);
	return 0;
}

        以上代码的结果为AAA,看来,指针类型只关心指向内容的大小,对于怎么解读指向的机器码,指针并不关心,写成char* 或者int*... ,不过是为了代码逻辑可读性。

  • 19
    点赞
  • 18
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值