”工欲善其事,必先利其器。“—孔子《论语.录灵公》
首页 > 编程 > C 中的内存布局

C 中的内存布局

发布于2024-08-17
浏览:747

介绍

内存布局是指计算机内存的组织和结构方式。它定义了各种系统组件如何划分和使用内存。

这在 C 中至关重要,因为它直接影响执行期间变量、函数和数据结构的存储和访问方式。

在本文中,我们将了解 C 中内存布局的基本方面。

C 内存布局中的段

C中的内存布局由不同的段组成,下面是段;

  1. 文本(代码)段。
  2. 数据段。
  3. 堆。
  4. 堆。

下图描述了C的内存布局。

Diagram of C’s memory layout.
现在让我们详细讨论这些部分。

文本(代码)段

文本段是C程序中存储编译后的机器代码指令的内存区域。这些指令构成了程序的可执行逻辑,并负责定义其行为。

下面通过一个简单的例子来说明C程序中文本段的概念:

#include 

int main() {
    int x = 5;
    int y = 10;
    int sum;

    sum = x   y;
    printf("The sum of %d and %d is %d\n", x, y, sum);

    return 0;
}

编译此程序时,编译器将源代码转换为机器代码。该机器代码构成了程序的逻辑和行为,并存储在文本段中。

虽然我们无法直接看到机器码。我们可以理解为文本段包含编译后的指令。

本质上,文本段包含定义程序执行时如何行为的指令。

数据段

数据段分为两部分:

  • 初始化数据段
  • 未初始化的数据段

初始化数据段

初始化数据段由全局变量、外部变量、静态变量(局部变量和全局变量)以及预先初始化的常量全局变量组成。初始化的数据段有两个部分,只读读写部分。

具有可以修改的预定义值的变量,即初始化的全局变量、外部变量和静态(本地和全局)变量存储在 读写部分中。另一方面,常量变量位于 只读 部分。

下面是一个示例,说明了存储在初始化数据段中的变量,包括读写部分和只读部分:

#include 

// Global variable (read-write section)
int globalVar = 10;

// External variable declaration (read-write section)
extern int externVar;

// Static global variable (read-write section)
static int staticGlobalVar = 20;

// Constant global variable (read-only section)
const int constGlobalVar = 30;

int main() {
    globalVar  = 5;
    staticGlobalVar  = 10;

    printf("Global variable: %d\n", globalVar);
    printf("Extern variable: %d\n", externVar);  // Assuming externVar is defined in another file
    printf("Static global variable: %d\n", staticGlobalVar);
    printf("Constant global variable: %d\n", constGlobalVar);

    return 0;
}

这说明了存储在初始化数据段的读写和只读部分中的变量。

未初始化的数据段

未初始化的数据段也称为BSS(由符号开始的块)段由未初始化的全局变量、外部变量和静态(局部和全局)变量组成。

这些变量在程序执行之前默认初始化为零。他们具有读写权限。从而允许在程序执行期间读取和写入它们。

例子:

#include 

// Uninitialized global variable (goes to the BSS segment)
int globalVar;

// Uninitialized static global variable (also goes to the BSS segment)
static int staticGlobalVar;

int main() {
    // Uninitialized local static variable (goes to the BSS segment)
    static int staticLocalVar;

    printf("Uninitialized Global Variable: %d\n", globalVar);
    printf("Uninitialized Static Global Variable: %d\n", staticGlobalVar);
    printf("Uninitialized Static Local Variable: %d\n", staticLocalVar);
    return 0;
}

在此程序中,未初始化的变量默认包含零或空值。这是由于编译器自动初始化造成的。这显示了存储在 BSS 段中的变量的行为。

堆是用于运行时动态内存分配的内存区域。这允许在程序执行期间根据需要分配和释放内存。 malloc()calloc()realloc()free()等函数用于内存分配和释放在堆中。程序的所有部分都可以访问堆。

例子:

#include 
#include 

int main() {
    // Dynamically allocate memory for an integer variable on the heap
    int *ptr = (int *)malloc(sizeof(int));

    return 0;
    }

此代码片段演示了 C 中动态内存分配的简单用法。它引起人们对请求内存、初始化指向该内存的指针以及正确管理内存以避免泄漏所涉及的步骤的关注。虽然此示例中不包括错误处理和内存释放,但它们是实际应用中使用动态内存的关键组成部分。

堆栈段主要功能是管理函数调用和存储局部变量。这部分在程序的内存布局中至关重要,因为它控制程序内的流程。堆栈采用后进先出(LIFO)结构,这意味着最近添加的数据将首先被删除。这使得堆栈对于管理局部变量和嵌套函数调用非常有效。

例子:

#include 

void functionA(int n) {
    int a = n   1; // Local variable
    printf("In functionA, a = %d\n", a);
}

void functionB() {
    int b = 10; // Local variable
    printf("In functionB, b = %d\n", b);
    functionA(b); // Call to functionA
}

int main() {
    int x = 20; // Local variable
    printf("In main, x = %d\n", x);
    functionB(); // Call to functionB
    return 0;
}

代码解释了栈帧如何存储局部变量。新的堆栈帧由函数调用创建,并在函数返回时被消除。 printf 指令有助于每个函数的局部变量值的可视化。执行流程遵循函数的调用和返回。

结论

C 程序员可以通过掌握这些概念来提高他们的编码技术并更好地理解他们的程序如何与内存交互。无论您是在优化性能还是解决复杂问题,了解内存布局都是编程工具箱中的一项重要技能。

欢迎关注、评论、点赞。快乐编码!

让我们在 LinkedIn 上联系吧。

版本声明 本文转载于:https://dev.to/hyoukarh/memory-layout-in-c-399a如有侵犯,请联系[email protected]删除
最新教程 更多>
  • 如何将PANDAS DataFrame列转换为DateTime格式并按日期过滤?
    如何将PANDAS DataFrame列转换为DateTime格式并按日期过滤?
    Transform Pandas DataFrame Column to DateTime FormatScenario:Data within a Pandas DataFrame often exists in various formats, including strings.使用时间数据时...
    编程 发布于2025-07-06
  • PHP SimpleXML解析带命名空间冒号的XML方法
    PHP SimpleXML解析带命名空间冒号的XML方法
    在php 很少,请使用该限制很大,很少有很高。例如:这种技术可确保可以通过遍历XML树和使用儿童()方法()方法的XML树和切换名称空间来访问名称空间内的元素。
    编程 发布于2025-07-06
  • 如何将来自三个MySQL表的数据组合到新表中?
    如何将来自三个MySQL表的数据组合到新表中?
    mysql:从三个表和列的新表创建新表 答案:为了实现这一目标,您可以利用一个3-way Join。 选择p。*,d.content作为年龄 来自人为p的人 加入d.person_id = p.id上的d的详细信息 加入T.Id = d.detail_id的分类法 其中t.taxonomy =...
    编程 发布于2025-07-06
  • 为什么不````''{margin:0; }`始终删除CSS中的最高边距?
    为什么不````''{margin:0; }`始终删除CSS中的最高边距?
    在CSS 问题:不正确的代码: 全球范围将所有余量重置为零,如提供的代码所建议的,可能会导致意外的副作用。解决特定的保证金问题是更建议的。 例如,在提供的示例中,将以下代码添加到CSS中,将解决余量问题: body H1 { 保证金顶:-40px; } 此方法更精确,避免了由全局保证金重置引...
    编程 发布于2025-07-06
  • 为什么HTML无法打印页码及解决方案
    为什么HTML无法打印页码及解决方案
    无法在html页面上打印页码? @page规则在@Media内部和外部都无济于事。 HTML:Customization:@page { margin: 10%; @top-center { font-family: sans-serif; font-weight: bo...
    编程 发布于2025-07-06
  • 将图片浮动到底部右侧并环绕文字的技巧
    将图片浮动到底部右侧并环绕文字的技巧
    在Web设计中围绕在Web设计中,有时可以将图像浮动到页面右下角,从而使文本围绕它缠绕。这可以在有效地展示图像的同时创建一个吸引人的视觉效果。 css位置在右下角,使用css float and clear properties: img { 浮点:对; ...
    编程 发布于2025-07-06
  • 如何从Google API中检索最新的jQuery库?
    如何从Google API中检索最新的jQuery库?
    从Google APIS 问题中提供的jQuery URL是版本1.2.6。对于检索最新版本,以前有一种使用特定版本编号的替代方法,它是使用以下语法:获取最新版本:未压缩)While these legacy URLs still remain in use, it is recommended ...
    编程 发布于2025-07-06
  • 图片在Chrome中为何仍有边框?`border: none;`无效解决方案
    图片在Chrome中为何仍有边框?`border: none;`无效解决方案
    在chrome 中删除一个频繁的问题时,在与Chrome and IE9中的图像一起工作时,遇到了一个频繁的问题。和“边境:无;”在CSS中。要解决此问题,请考虑以下方法: Chrome具有忽略“ border:none; none;”的已知错误,风格。要解决此问题,请使用以下CSS ID块创建带...
    编程 发布于2025-07-06
  • FastAPI自定义404页面创建指南
    FastAPI自定义404页面创建指南
    response = await call_next(request) if response.status_code == 404: return RedirectResponse("https://fastapi.tiangolo.com") else: ...
    编程 发布于2025-07-06
  • 如何修复\“常规错误:2006 MySQL Server在插入数据时已经消失\”?
    如何修复\“常规错误:2006 MySQL Server在插入数据时已经消失\”?
    How to Resolve "General error: 2006 MySQL server has gone away" While Inserting RecordsIntroduction:Inserting data into a MySQL database can...
    编程 发布于2025-07-06
  • Python环境变量的访问与管理方法
    Python环境变量的访问与管理方法
    Accessing Environment Variables in PythonTo access environment variables in Python, utilize the os.environ object, which represents a mapping of envir...
    编程 发布于2025-07-06
  • C++成员函数指针正确传递方法
    C++成员函数指针正确传递方法
    如何将成员函数置于c 的函数时,接受成员函数指针的函数时,必须同时提供对象的指针,并提供指针和指针到函数。需要具有一定签名的功能指针。要通过成员函数,您需要同时提供对象指针(此)和成员函数指针。这可以通过修改Menubutton :: SetButton()(如下所示:[&& && && &&华)...
    编程 发布于2025-07-06
  • eval()vs. ast.literal_eval():对于用户输入,哪个Python函数更安全?
    eval()vs. ast.literal_eval():对于用户输入,哪个Python函数更安全?
    称量()和ast.literal_eval()中的Python Security 在使用用户输入时,必须优先确保安全性。强大的Python功能Eval()通常是作为潜在解决方案而出现的,但担心其潜在风险。 This article delves into the differences betwee...
    编程 发布于2025-07-06
  • 解决MySQL插入Emoji时出现的\\"字符串值错误\\"异常
    解决MySQL插入Emoji时出现的\\"字符串值错误\\"异常
    Resolving Incorrect String Value Exception When Inserting EmojiWhen attempting to insert a string containing emoji characters into a MySQL database us...
    编程 发布于2025-07-06
  • 如何使用Depimal.parse()中的指数表示法中的数字?
    如何使用Depimal.parse()中的指数表示法中的数字?
    在尝试使用Decimal.parse(“ 1.2345e-02”中的指数符号表示法时,您可能会出现错误。这是因为默认解析方法无法识别指数符号。 成功解析这样的字符串,您需要明确指定它代表浮点数。您可以使用numbersTyles.Float样式进行此操作,如下所示:[&& && && &&华氏度D...
    编程 发布于2025-07-06

免责声明: 提供的所有资源部分来自互联网,如果有侵犯您的版权或其他权益,请说明详细缘由并提供版权或权益证明然后发到邮箱:[email protected] 我们会第一时间内为您处理。

Copyright© 2022 湘ICP备2022001581号-3