9. 指针访问内存的高级用法
本节课我们讲解指针访问内存的高级用法,本节的内容在 C 语言中非常常用,但难于理解。为了能让我的朋友们快速理解本节内容,我们先来复习一下我们前面说过的几个概念。
- 指针的是一个变量,它的内部保存的是指向变量的内存地址。
- 指针解引用 返回的数据是指针指向的变量的引用。
- 指针解引用 后能够引用的内存数据范围和指针本身的类型相关。
- 指针解引用 后能够引用的数据类型是指针类型去掉一个星号(
*)后的类型,如:指针p的类型为char*,则解引用后*p的类型为char。
既然 指针解引用 后能够引用的内存数据范围和指针本身的类型相关,那么我们就可以使用这个规则对内存进行重新定义类型,这样可以方便对内存的操作。
下面举例说明
在 IP 协议中,网络层传输的 IPv4 的地址通常用一个无符号型的 32 位整数表示,如要表示 192.168.1.100 的 IP 地址可以用无符号型 int 类型存储。如:
unsigned int ipv4 = (192 << 24) | (168 << 16) | (1 << 8) | (100 << 0);
那么我们如何得到每个字节的呢?我们知道 unsigned char * 类型的指针解引用后每次只能访问一个字节。基于这个思想。我们定义指针如下:
unsigned char * pc = (unsigned char *) &ipv4;
这样我们就使用指针 pc 指向了 变量 ipv4 的起始地址。再通过指针的运算,我们就可以得到每个字节数据了。比如:ipv4 最高字节的数据可以使用 *(pc+3) 获取;ipv4 最高字节的数据可以使用 *pc 获取。
完整示例如下:
// filename: pointer_adv.c
#include <stdio.h>
int main(int argc, char *argv[]) {
unsigned int ipv4 = (192 << 24) | (168 << 16) | (1 << 8) | (100 << 0);
unsigned char * pc = (unsigned char *) &ipv4;
// 以点分隔的方式打印 IPv4 的地址。
printf("ipv4 address: %d.%d.%d.%d\n", *(pc+3), *(pc+2), *(pc+1), *(pc+0));
return 0;
}
运行结果如下:
weimingze@mzstudio:~$ gcc -o pointer_adv pointer_adv.c
weimingze@mzstudio:~$ ./pointer_adv
ipv4 address: 192.168.1.100
练习:
已知一个 unsigned short int 类型的变量 s 的值为 0x0102,即十进制的 258。使用指针将 s 的高位字节修改为 0x02,低位字节修改为 0x04,最后打印修改后的值。
#include <stdio.h>
int main(int argc, char *argv[]) {
unsigned short int s = 0x0102;
// ... 完成此处的代码。
printf("s: %#06x\n", s); // 打印 s: 0x0204
return 0;
}