主页 > 创业  > 

深⼊理解指针(1)

深⼊理解指针(1)
1. 内存和地址   1.1 内存          我们知道计算机上CPU(中央处理器)在处理数据的时候,需要的数据是在内存中读取的,处理后的 数据也会放回内存中。              那这些内存空间如何高效的管理呢?                其实也是 把内存划分为⼀个个的内存单元,每个内存单元的大小取1个字节。   计算机中常见的单位(补充): ⼀个比特位可以存储⼀个2进制的位1或者0     内存单元的编号 == 地址 == 指针   举例说明:     1.2 究竟该如何理解编址   计算机中的编址,并不是把每个字节的地址记录下来,而是通过硬件设计完成的。                 硬件与硬件之间是互相独立的,那么如何通信呢? 答案很简单,用 "线"连起来。   而CPU和内存之间也是有⼤量的数据交互的,所 以,两者必须也用线连起来。   地址信息被下达给内存,在内存上,就可以找到 该地址对应的数据,将数据在通过数据总线传入 CPU内寄存器。     2. 指针变量和地址   2.1 取地址操作符(&)   在C语言中创建变量其实就是向内存申请空间,比如: #include <stdio.h> int main() { int a = 10; return 0; }

比如,上述的代码就是创建了整型变量a,内存中 申请4个字节,用于存放整数10,其中每个字节都有地址   通过⼀个操作符(&)-取地址操作符得到a的地址。     &a取出的是a所占4个字节中地址较小的字节的地址。   虽然整型变量占用4个字节,我们只要知道了第⼀个字节地址,顺藤摸瓜访问到4个字节的数据也是可行的。  

 2.2 指针变量和解引用操作符(*)

2.2.1 指针变量   那我们 通过取地址操作符(&)拿到的地址是⼀个数值,那地址值存放在哪里呢?   答案是: 指针变量中。   比如: #include <stdio.h> int main() { int a = 10; int * pa = &a;//取出a的地址并存储到指针变量pa中 return 0; 指针变量也是⼀种变量,这种变量就是用来存放地址的,存放在指针变量中的值都会理解为地址。   2.2.2 如何拆解指针类型   我们看到pa的类型是 int* ,我们该如何理解指针的类型呢?   int a = 10; int * pa = &a; 这里pa左边写的是 int* , * 表示pa是指针变量, int 表示pa指向的变量a的类型是整型   2.2.3 解引用操作符(*)   int main() { int a = 100; int* pa = &a; *pa = 0; return 0; } 上面代码中就使用了解引用操作符, *pa 的意思就是通过pa中存放的地址,找到指向的空间,*pa其实就是a变量了;所以*pa = 0,这个操作符是把a改成了0.     2.3 指针变量的大小   #include <stdio.h> //指针变量的⼤⼩取决于地址的⼤⼩ //32位平台下地址是32个bit位(即4个字节) //64位平台下地址是64个bit位(即8个字节) int main() { printf("%zd\n", sizeof(char *)); printf("%zd\n", sizeof(short *)); printf("%zd\n", sizeof(int *)); printf("%zd\n", sizeof(double *)); return 0; }

 

 

3. 指针变量类型的意义 

3.1 指针的解引用   对比,下面2段代码,主要在调试时观察内存的变化 //代码1 #include <stdio.h> int main() { int n = 0x11223344; int *pi = &n; *pi = 0; return 0; } //代码2 #include <stdio.h> int main() { int n = 0x11223344; char *pc = (char *)&n; *pc = 0; return 0; }        调试我们可以看到,代码1会将n的4个字节全部改为0,但是代码2只是将n的第⼀个字节改为0。                          

3.2 指针+-整数

先看⼀段代码,调试观察地址的变化

#include <stdio.h> int main() { int n = 10; char *pc = (char*)&n; int *pi = &n; printf("%p\n", &n); printf("%p\n", pc); printf("%p\n", pc+1); printf("%p\n", pi); printf("%p\n", pi+1); return 0; } 代码运行的结果如下:           我们可以看出, char* 类型的指针变量+1跳过1个字节, int* 类型的指针变量+1跳过了4个字节。         这就是指针变量的类型差异带来的变化。指针+1,其实跳过1个指针指向的元素。指针可以+1,那也可以-1。   结论:指针的类型决定了指针向前或者向后走⼀步有多大(距离)。   3.3 void* 指针          在指针类型中有⼀种特殊的类型是 void * 类型的,可以理解为无具体类型的指针(或者叫泛型指针),这种类型的指针可以用来 接受任意类型地址(垃圾堆)。          但是也有局限性, void* 类型的指针不能直接进 行指针的+-整数和解引用的运算。   举例: int main() { int a = 10; int* pa = &a; char* pc = &a; return 0; }        在上面的代码中,将⼀个int类型的变量的地址赋值给⼀个char*类型的指针变量。编译器给出了⼀个警告(如下图),是因为类型不兼容。而使用void*类型就不会有这样的问题。     使用void*类型的指针接收地址:   #include <stdio.h> int main() { int a = 10; void* pa = &a; void* pc = &a; *pa = 10; *pc = 0; return 0; } VS编译代码的结果:            void* 类型的指针可以接收不同类型的地址,但是无法直接进行指针运算。   那么 void* 类型的指针到底有什么用呢?                 ⼀般 void* 类型的指针是使用在函数参数的部分,用来接收不同类型数据的地址,这样的设计可以实现泛型编程的效果,使得⼀个函数来处理多种类型的数据。

 

标签:

深⼊理解指针(1)由讯客互联创业栏目发布,感谢您对讯客互联的认可,以及对我们原创作品以及文章的青睐,非常欢迎各位朋友分享到个人网站或者朋友圈,但转载请说明文章出处“深⼊理解指针(1)