1.指针与数组头等价又不等价
-
等价在于数组名可以当作指针使用;
-
不等价在于:
int a[6] = {0, 1, 2, 3, 4, 5}; int *p = a; int len_a = sizeof(a) / sizeof(int); int len_p = sizeof(p) / sizeof(int); printf("len_a = %d, len_p = %d\n", len_a, len_p); /*输出为: len_a = 6, len_p = 1 */
sizeof 就是根据符号的类型来计算长度的。对于数组 a,它的类型是int [6]。对于指针变量 p,它的类型是int *,两者类型不同。
2.用指针做函数返回的注意点
先看代码,猜猜输出什么:
-
int *func(){ int n = 100; return &n; } int main(){ int *p = func(); printf("test value = %d\n", *p); printf("test value = %d\n", *p); return 0; } /*输出结果为: test value = 100 test value = -2 */
由于返回的是函数内的局部定义变量,函数运行结束后会丢弃所有的局部数据。这里的丢弃不是说销毁抹掉数据,而是释放了局部数据所占用内存的使用权限,后面的代码可以使用这块内存,因此会被其他函数调用后覆盖这块内存。
3.虚拟地址与映射
现代操作系统使用分页机制来管理内存,使得每个程序都有自己的地址空间,每当程序使用虚拟地址进行读写时,都必须转换为实际的物理地址。内存地址的转换是通过一种叫做页表(Page Table)的机制来完成的。
虚拟地址的作用:能够使得不同程序的地址空间相互隔离,提高内存使用效率。如果每个程序直接使用物理地址内存,那么程序之间所用的地址空间不是相互隔离的。恶意程序或bug程序易于改写其他程序的内存数据以致程序崩溃。
提高虚拟地址,必须要说到一个硬件部件:MMU(Memory Management Unit),由它来负责将虚拟地址映射为物理地址。