美文网首页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++的内存分区问题~ C++内存分区 C++程序的内存分区可划分为四大内存分区:堆、栈、全局/静态存...

  • C++_day06

    C++核心编程 主要针对C++面向对象编程技术做详细讲解,探讨C++中的核心和精髓 1. 内存分区模型 C++程序...

  • C++基础一文通(三)内存分区、引用

    一. c++ 内存分区机制 请阅读这篇文章: C++内存分区[https://www.cnblogs.com/Br...

  • C++内存分区模型

    内存分区模型 C++程序在执行时,将程序大方向划分为4个区域 代码区:存放函数体的二进制代码,由操作系统进行管理的...

  • C/C++内存分区模型

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

  • 百度Linux C++后台开发面试题(个人整理)

    1、C/C++程序的内存分区 其实C和C++的内存分区还是有一定区别的,但此处不作区分: 1) 、栈区(stack...

  • C++内存管理与程序内存分区

    C++内存分区 C++存在如下的内存分区 1)栈区(stack):由编译器自动分配释放 ,存放函数的 参数值,局部...

  • C/C++ 内存分区

    注:转载自 https://fishc.com.cn/blog-9-182.html 在C/C++中,内存分成5个...

  • 2018-11-11 #C++ 内存模型#

    C++ 原子操作内存模型 C++ 原子操作内存模型解决并发编程的什么问题? 相信在大多数应用程序员眼里,代码在编辑...

  • C++内存分析模型

    1 内存分区模型 C++程序在执行时,将内存大方向划分为4个区域 代码区:存放函数体的二进制代码,由操作系统进行管...

网友评论

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

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