C/C++程序内存分布

1,主要段及其分布

    每个程序运行起来以后,它将拥有自己独立的虚拟地址空间。这个虚拟地址空间的大小与操作系统的位数有关系。例如32位硬件平台的虚拟地址空间的地址可以从0~2^32-1,即0x00000000~0xFFFFFFFF,总共4GB大小。在32位Windows操作系统中,高地址的2GB位内核空间,用户空间只有2GB,而32位Linux的内核空间只有1GB,用户空间有3GB大小。而64位操作系统,用户可用空间则要大的多。C/C++程序在虚拟内存中的排布大概如下所示(仅仅列出了相关的主要段):
C/C++程序内存分布_第1张图片
    如上图所示,一个由C/C++编译的程序占用的内存分为以下几个部分 :
    1、栈区(stack)— 由编译器自动分配释放 ,存放函数的参数值,局部变量的值等。其
操作方式类似于数据结构中的栈。
    2、堆区(heap) — 一般由程序员分配释放, 若程序员不释放,程序结束时可能由OS回
收 。注意它与数据结构中的堆是两回事,分配方式倒是类似于链表,呵呵。
    3、全局区(静态区)(static)—,全局变量和静态变量的存储是放在一块的,初始化的
全局变量和静态变量在一块区域, 未初始化的全局变量和未初始化的静态变量在相邻的另
一块区域。 - 程序结束后由系统释放。
    4、文字(只读)常量区 —常量字符串就是放在这里的。 程序结束后由系统释放
    5、代码段—存放函数体的二进制代码,直接的操作数也是存储在这个位置的。如int a=4;。

2,文字常量和常变量

    文字常量又称为“字面常量”,包括数值常量、字符常量和符号常量。其特点是编译后写在代码区,不可寻址,不可更改,属于指令的一部分。因此像如下的代码是无法编译的:

int& r=1;   //编译错误

    但是如下代码确实可以通过编译的。主要原因是const int _r=1;_r存储在只读常量区,对其建立引用自然是合理的。

const int& r=1;

文字常量的主要类型如下图所示:
C/C++程序内存分布_第2张图片
    常变量指定义时必须显示初始化且值不可修改的变量。与普通变量一样被分配空间,因此是可以寻址的。鉴别常变量的一个简单方法是查看变量是否有const关键字。
常变量包括全局常变量和局部常变量。
二者的区别在于:
    1,全局常变量存储在只读常量区,其不可修改性由操作系统保障。
    2,局部常变量存储在栈区,其不可修改性仅仅是由编译器来保证,因此可以用const_cast

3,字符串和字符数组的存储位置

    字符串和字符数组的存储位置如下所示:

char *returnStr()
{
    static char p[] = "hello world!";//虽然是函数内部,但是由于是static,存储在全局区(静态区)
    return p;
}

char *returnArray()
{
    char p[] = "hello world!";//hello world!在只读数据段,但同时在栈上也会开辟一块空间,然后复制进去
    return p;//事实上返回了栈内存
}

int main()
{
    char str1[] = "hello,world";//栈区,运行时赋值
    char str2[] = "hello,world";//栈区

    const char str3[] = "hello,world";
    const char str4[] = "hello,world";

    const char *str5 = "hello,world";//字符串常量,只读常量区
    const char *str6 = "hello,world";//只读常量区

    return 0;
}

你可能感兴趣的:(C/C++)