【c语言学习】内存与变量存储

内存与变量存储

内存的分区

在C语言中,进程的内存空间可以被分为以下几个主要部分:

在这里插入图片描述

这些内存分区通常被称为虚拟内存分区,因为它们是在程序运行时由操作系统和编译器管理的逻辑上的分区,而不是物理上的。

了解内存分区对于理解程序和内存管理是非常重要的,各个分区的详情如下:

  • 堆区(Heap):堆区是动态分配内存的区域,程序员可以通过malloc()calloc()等函数在堆上动态分配内存,并通过free()函数释放堆上的内存。堆区的大小在程序运行时可以动态变化。

  • 栈区(Stack):栈区用于存储函数的局部变量、函数参数以及函数调用的返回地址等信息。每次函数调用时,都会在栈上分配一定的空间。栈是一种后进先出(LIFO)的数据结构。栈上的内存分配和释放由编译器自动管理,不需要程序员显式地进行操作。

  • 全局区(Global Area):全局区包括了全局变量和静态变量的存储空间。全局变量在程序启动时被初始化,一直存在于整个程序的运行过程中。静态变量也存储在全局区中,但其作用域仅限于定义它的源文件。全局区在程序运行期间一直存在,直到程序结束。

  • 文字常量区(Text Constants Area):文字常量区存储不可修改的常量值,包括字符串常量、字符常量、整数常量、浮点数常量等。这些常量在程序编译时被确定,并分配到文字常量区,在程序执行期间一直存在。文字常量区通常是只读的,因此任何试图修改文字常量区中的值的操作都会导致错误。这种只读的特性保证了程序中的常量数据的安全性和一致性。

  • 代码区(Code Segment):代码区存储了程序的机器代码,也称为指令区或者文本区。在程序执行时,CPU会从代码区读取指令并执行。代码区通常是只读的,因为程序的机器代码在运行时不应该被修改。

    这些区域的具体实现和分配可能会因编译器、操作系统和具体的程序而有所不同,但通常遵循类似的规则和概念。

变量的存储类别

在C语言中,变量的存储类别决定了变量的存储位置、生命周期和作用域。我们就这几个方面对各个存储类型的变量做详细介绍。

普通局部变量

作用范围当前代码块内部
生命周期从其定义的位置开始,到其所在的代码块执行完毕为止。
存储区域栈区

注意:

  • 代码块由一对花括号 {} 包围的一组语句构成。
  • 如果全局变量和局部变量同名,遵循就近原则。
  • 普通局部变量不初始化其内容不确定。

案例:

#include <stdio.h>

int data = 10; // 全局变量

void testo1()
{
    int data = 20;        // 局部变量
    printf("%d\n", data); // 就近原则
    return;
}
int main(int argc, char const *argv[])
{
    testo1();
    return 0;
}

运行结果:

20

普通全局变量

作用范围当前源文件或其源文件
生命周期从程序启动时创建该变量开始,直到程序结束时销毁为止。
存储区域全局区

注意:

  • 普通全局变量不初始化,默认为0
  • 如果需要使用其他源文件的全局变量需要加extern

案例:

int data = 10; // 在其他源文件中定义全局变量
//test_extern.c
#include <stdio.h>
extern int data; // 声明全局变量
void testo1()
{
    printf("%d ", data);
    return;
}
int main(int argc, char const *argv[])
{
    testo1();
    return 0;
}
//test.c

运行结果:

10

因为涉及到两个源文件,在编译的时候也需要编译两个源文件

静态局部变量

作用范围当前代码块
生命周期从程序启动时创建该变量开始,直到程序结束时销毁为止。
存储区域全局区

注意:

  • 静态局部变量不初始化内容为0
  • 静态局部变量只会定义一次

案例:

#include <stdio.h>

void testo1()
{
    static int data = 10; // 定义静态局部变量
    data++;
    printf("data=%d\n", data);
    return;
}
int main(int argc, char const *argv[])
{
    // 多次调用test01()
    testo1();
    testo1();
    testo1();
    testo1();
    return 0;
}

运行结果:

data=11
data=12
data=13
data=14

静态全局变量

作用范围当前源文件
生命周期从程序启动时创建该变量开始,直到程序结束时销毁为止。
存储区域全局区

注意:

  • 静态局部变量不初始化内容为0
  • 只能在当前源文件使用

案例:

static data = 10; // 在其他源文件中定义静态全局变量
//test_extern.c
#include <stdio.h>
extern extern int data; // 声明静态全局变量
void testo1()
{

    printf("data=%d\n", data);
    return;
}
int main(int argc, char const *argv[])
{
    testo1();

    return 0;
}
//test.c

编译错误:

test.c:2:1: error: duplicate ‘extern’
    2 | extern extern int data; // 声明静态全局变量
      | ^~~~~~
test_extern.c:1:8: warning: type defaults to ‘int’ in declaration of ‘data’ [-Wimplicit-int]
    1 | static data = 10; // 在其他源文件中定义静态全局变量

寄存器变量

作用范围当前代码块
生命周期从其定义的位置开始,到其所在的代码块执行完毕为止。
存储区域寄存器

注意:

  • 虽然寄存器变量的声明要求编译器将其存储在寄存器中,但是实际情况可能会因为寄存器数量的限制、编译器的实现以及编译器的优化策略等因素而不同。如果编译器无法将变量存储在寄存器中,它会像普通的自动变量一样存储在内存中。

  • 26
    点赞
  • 14
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值