《征服C指针》——读书笔记(3)

来源:互联网 发布:mac配套手绘板 编辑:程序博客网 时间:2024/05/21 10:25

一、虚拟地址

       当今的操作系统都会给应用程序的每一个进程分配独立的“虚拟地址空间”。这和 C 语言本身并没有关系,而是操作系统和 CPU 协同工作的结果。正是因为操作系统和 CPU 努力地为每一个进程分配独立的地址空间,所以就算我毛手毛脚、糊里糊涂地制造了一个 bug,破坏了某个内存区域,顶多也就是让当前的应用程序趴窝,但不会影响其他进程。

        当然了,真正去保存内存数据的还是物理内存。操作系统负责将物理内存分配给虚拟地址空间,同时还会对每一个内存区域设定“只读”或者“可读写”等属性。通常,因为程序的执行代码是只读的,所以有时候会和其他进程共享物理内存。正是因为避免了让应用程序直接面对物理内存的地址,操作系统才能够顺利地对内存区域进行重新配置,如下图所示。


要点:

       在如今的运行环境中,应用程序面对的是虚拟地址空间。



二、C的变量的种类

1. 按作用域划分

    1)全局变量:全局变量在任何地方都是可见的。当程序被分割为多个源代码文件进行编译时,声明为全局变量的变量也是可以从其他源代码文件中引用的。

    2)静态变量:就算对于像全局变量那样被定义在函数外面的变量,一旦添加了 static,作用域就只限定在当前所在的源代码文件中。通过 static 指定的变量(包括函数),对于其他源代码文件是不可见的。

    3)局部变量:局部变量是指在函数中声明的变量。局部变量只能在包含它的声明的语句块(使用{ }括起来的范围)中被引用,局部变量通常在它所在的语句块结束的时候被释放。

2. 按存储期划分

    1)静态存储期:全局变量、文件内的 static 变量、指定 static 的局部变量都持有静态存储期。这些变量被统称为静态变量。 持有静态存储期的变量的寿命从程序运行时开始,到程序关闭时结束。换句话说,静态变量一直存在于内存的同一个地址上。

    2)自动存储期:没有指定 static 的局部变量,持有自动存储期。这样的变量被称为自动变量。 持有自动存储期的变量,在程序运行进入它所在的语句块时被分配以内存区域,该语句块执行结束后这片内存区域被释放。

    3)非变量:C 中可以使用 malloc()函数动态分配内存。通过 malloc()动态分配的内存,寿命一直延续到使用 free()释放它为止。


要点:

C中有3种内存领域的寿命

1. 静态变量的寿命从程序运行时开始,到程序关闭时结束。

2. 自动变量的寿命到声明该变量的语句块执行结束为止。

3. 通过 malloc() 分配的领域的寿命到调用 free() 为止。



三、输出地址

示例代码:

#include <stdio.h>#include <stdlib.h>int global_var;static int file_static_var;void func1(void){int func1_var;static int func1_static_var;printf("&func1_var..%p\n", &func1_var);printf("&func1_static_var..%p\n", &func1_static_var);}void func2(void){int func2_var;printf("&func2_var..%p\n", &func2_var);}int main(void){int *p;/* 输出指向函数的指针 */printf("&func1..%p\n", func1);printf("&func2..%p\n", func2);/* 输出字符串常量的地址 */printf("string literal..%p\n", "abc");/* 输出全局变量 */printf("&global_var..%p\n", &global_var);/* 输出文件内的static变量的地址 */printf("&file_static_var..%p\n", &file_static_var);/* 输出局部变量 */func1();func2();/* 通过malloc申请的内存区域的地址 */p = malloc(sizeof(int));printf("malloc address..%p\n", p);return 0;}

输出结果:

&func1..0x8048414 &func2..0x8048440 string literal..0x8048551&global_variable..0x804965c &file_static_variable..0x8049654 &func1_variable..0xbfbfd9d8 &func1_static_variable..0x8049650 &func2_variable..0xbfbfd9d8 malloc address..0x805b030


       在 C 中,正如数组在表达式中可以被解读成指针一样,“函数”也同时意味着“指向函数的指针”。通常,这个指针指向函数的初始地址。

       在 C 中,“字符串”是作为“char 的数组”来表现的。字符串常量类型也是“char 的数组”,因为表达式中的数组可以解读成“指向初始元素的指针”,所以表达式中的“abc”,同样也意味着保存这个字符串内存区域的初始地址。

       对输出地址进行整理,得到下表:

地址内容0x8048414函数func1()的地址0x8048440函数func2()的地址0x8048551字符串常量0x8049650函数内static变量0x8049654文件内static变量0x804965c全局变量0x805b030malloc()分配的内存0xbfbfd9d8func1()的自动变量0xbfbfd9d8func2()的自动变量
       通过观察,我们发现“指向函数的指针”和“字符串常量”被配置在非常近的内存区域。此外,函数内 static 变量、文件内 static 变量、全局变量等这些静态变量,也是被配置在非常近的内存区域。接下来就是 malloc() 分配的内存区域,它看上去和自动变量的区域离得很远。最后你可以发现,func1()和 func2()的自动变量被分配了完全相同的内存地址。 如果使用图来说明,应该是下面这样的感觉


0 0
原创粉丝点击