美文网首页C++
C/C++内存分区模型

C/C++内存分区模型

作者: 温暖春阳 | 来源:发表于2018-03-31 22:28 被阅读11次
    #define _CRT_SECURE_NO_WARNINGS
    #include<stdio.h>
    #include<string.h>
    #include<stdlib.h>
    
    
    //extern int a = 10; 默认外部链接
    int a = 10; //全局区
    //静态全局变量是内部链接
    static int b = 20; //静态区
    
    //内部链接和外部链接有什么区别?
    //1. 如果变量是内部链接的话,那么此变量只能在当前文件内访问
    //2. 如果是变量是外部链接的话,那么此变量可以被其他文件使用
    
    
    //1. 全局静态变量和局部静态变量都存储在静态区,都是在程序运行期间都是合法有效
    //2. 局部静态变量符号的可见范围仅限于当前函数内部,全局静态变量可见范围从定义到文件结尾
    
    //头文件不要放定义,只能放声明
    
    void test01()
    {
        static int c = 30; //静态区
    }
    
    //头文件不参与编译,每一个.c文件,我们叫做一个编译单元
    //编译器独立编译每一个.c文件
    void test02()
    {
        //声明,表示告诉编译器这个符号是存在的,你让我先编译通过,让连接器去找到底这个符号在那
        extern int g_a;
    
        printf("g_a = %d\n", g_a);
    }
    
    
    //--------------------------------------
    //常量区 字符串常量 全局const变量
    
    
    //1. const全局和局部变量区别?
    //const全局变量在常量区,不能修改(直接或者间接)
    const int g_c = 100;
    void test03()
    {
        //直接修改不行
        //g_c = 200;
    
        //间接修改也不行
        int *p = (int *)&g_c;
        *p = 200;
    
        //全局const放在常量区,一旦初始化,不能修改
    }
    
    //2. const局部变量
    void test04()
    {
        //栈上
        const int a = 100;
        //a = 200;
    
        int *p = (int *)&a;
        *p = 200;
    
        printf("a = %d\n", a);
    
    }
    
    
    void test05()
    {
        //"hello world!" char*类型字符串
    #if 0
        char *p = "hello world!";
    
        printf("%d\n", &"hello world!");
        printf("%d\n", p);
    
    
        printf("p = %s\n", p);
        p[0] = 'A';
        printf("p = %s\n", p);
    
    #endif
    
        char *p1 = "hello world!";
        char *p2 = "hello world!";
    
        printf("p1 = %d\n", p1);
        printf("p2 = %d\n", p2);
    }
    
    
    
    
    
    int main(){
    
        //test04();
        test05();
    
        system("pause");
        return EXIT_SUCCESS;
    }
    

    全局静态区内的变量在编译阶段已经分配好内存空间并初始化。这块内存在程序运行期间一直存在,它主要存储全局变量、静态变量和常量。

    注意:
    1. 这里不区分初始化和未初始化的数据区,是因为静态存储区内的变量若不显示初始化,则编译器会自动以默认的方式进行初始化,即静态存储区内不存在未初始化的变量。
    2. 全局静态存储区内的常量分为常变量和字符串常量,一经初始化,不可修改。静态存储内的常变量是全局变量,与局部常变量不同,区别在于局部常变量存放于栈,实际可间接通过指针或者引用进行修改,而全局常变量存放于静态常量区则不可以间接修改。
    3. 字符串常量存储在全局/静态存储区的常量区。
      示例代码:
    int v1 = 10;//全局/静态区
    const int v2 = 20; //常量,一旦初始化,不可修改
    static int v3 = 20; //全局/静态区
    char *p1; //全局/静态区,编译器默认初始化为NULL
    
    //那么全局static int 和 全局int变量有什么区别?
    
    void test()
    {
        static int v4 = 20; //全局/静态区
    }
    

    加深理解:

    char* func()
    {
        static char arr[] = "hello world!"; //在静态区存储 可读可写
        arr[2] = 'c';
        char* p = "hello world!"; //全局/静态区-字符串常量区 
        //p[2] = 'c'; //只读,不可修改 
        printf("%d\n",arr);
        printf("%d\n",p);
        printf("%s\n", arr);
        return arr;
    }
    void test()
    {
        char* p = func();
        printf("%s\n",p);
    }
    

    字符串常量是否可修改?字符串常量优化:

    ANSI C中规定:修改字符串常量,结果是未定义的。
    ANSI C并没有规定编译器的实现者对字符串的处理,例如:

    1. 有些编译器可修改字符串常量,有些编译器则不可修改字符串常量。
    2. 有些编译器把多个相同的字符串常量看成一个(这种优化可能出现在字符串常量中,节省空间),有些则不进行此优化。如果进行优化,则可能导致修改一个字符串常量导致另外的字符串常量也发生变化,结果不可知。
    所以尽量不要去修改字符串常量!

    总结

    在理解C/C++内存分区时,常会碰到如下术语:数据区,堆,栈,静态区,常量区,全局区,字符串常量区,文字常量区,代码区等等,初学者被搞得云里雾里。在这里,尝试捋清楚以上分区的关系。

    数据区包括:堆,栈,全局/静态存储区。

    • 全局/静态存储区包括:常量区,全局区、静态区。
    • 常量区包括:字符串常量区、常变量区。

    代码区:存放程序编译后的二进制代码,不可寻址区。

    可以说,C/C++内存分区其实只有两个,即代码区和数据区。

    相关文章

      网友评论

        本文标题:C/C++内存分区模型

        本文链接:https://www.haomeiwen.com/subject/ofbncftx.html