C语言中,指针是很重要的一个功能,但想要用好指针却不是一件容易的事,本篇从内存存储的数据出发,通过对比变量与指针在内存中究竟是怎么存储的,来对指针有一个直观的认识。
首先明确一个概念:变量,存储的是数值,而指针,是一种特殊的变量,它存储的是地址形式的数值。
下面编写一个测试程序来验证一下,该程序定义了一些变量与指针,另外,还使用malloc函数来动态申请内存(普通变量是存储在栈区,动态申请的变量在堆区,通过打印其内存地址可以看出差别)。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55
| #include <stdio.h> #include <stdlib.h>
int main() { int a = 0xFF01; char b = 23; int *p1 = &a;
short *p3;
char *p2; char arr[3] = {7,8,9}; p2 = arr; p3 = (short*)malloc(3*sizeof(short)); p3[0] = 0x110a; p3[1] = 0x220b; p3[2] = 0x7fff; printf("int a的内存地址: &a = %#x\r\n", &a); printf("int a存储的值: a = %#x\r\n", a); printf("\r\n"); printf("char b的内存地址: &b = %#x\r\n", &b); printf("char b存储的值: b = %#x\r\n", b); printf("\r\n"); printf("指针int *p1的内存地址: &p1 = %#x\r\n", &p1); printf("指针int *p1存储的值: p1 = %#x\r\n", p1); printf("指针int *p1指向的地址的值: *p1 = %#x\r\n", *p1); printf("\r\n"); printf("指针char *p2的内存地址: &p2 = %#x\r\n", &p2); printf("指针char *p2存储的值: p2 = %#x\r\n", p2); printf("指针char *p2指向的地址的值: *p2 = %d\r\n", *p2); printf("\r\n"); printf("数组arr[3]的内存地址: &arr = %#x\r\n", &arr); printf("数组元素arr[0]的内存地址: &arr[0] = %#x\r\n", &arr[0]); printf("数组元素arr[1]的内存地址: &arr[1] = %#x\r\n", &arr[1]); printf("数组元素arr[2]的内存地址: &arr[2] = %#x\r\n", &arr[2]); printf("\r\n");
printf("指针short *p3的内存地址: &p3 = %#x\r\n", &p3); printf("指针short *p3存储的值: p3 = %#x\r\n", p3); printf("指针short *p3指向的地址的值: *p3 = %d\r\n", *p3); printf("指针short *p3 malloc的p3[0]的内存地址: &p3[0] = %#x\r\n", &p3[0]); printf("指针short *p3 malloc的p3[1]的内存地址: &p3[1] = %#x\r\n", &p3[1]); printf("指针short *p3 malloc的p3[2]的内存地址: &p3[2] = %#x\r\n", &p3[2]); printf("\r\n"); return 0; }
|
测试程序输出如下结果:
通过VC6.0软件的调试功能,可以查看内存中的内容:
为便于分析,我做了一张对照图,如下:
可以看到:
- 普通变量在内存存储的是变量的值,指针存储的是指针性变量,即其它变量的地址,如图中的蓝色箭头
- 变量是以小端方式存储的(关于大小端的存储方式,可参考之前的文章:)
- 普通变量存储在栈区,栈的内容向下生长,动态分配的变量在堆区,堆的内容向上生长