メモリ レイアウトとは、コンピュータのメモリがどのように編成および構造化されているかを指します。これは、さまざまなシステム コンポーネントによってメモリがどのように分割され、利用されるかを定義します。
これは、実行中に変数、関数、データ構造がどのように保存されアクセスされるかに直接影響するため、C では非常に重要です。
この記事では、C のメモリ レイアウトの基本的な側面について学びます。
C のメモリ レイアウトはさまざまなセグメントで構成されます。以下にセグメントを示します。
下の図は C のメモリ レイアウトを示しています。
次に、セグメントについて詳しく説明します。
テキスト セグメントは、コンパイルされたマシン コード命令を格納する C プログラム内のメモリ領域です。これらの命令はプログラムの実行可能なロジックを構成し、その動作を定義する役割を果たします。
C プログラムのテキスト セグメントの概念を説明する簡単な例を次に示します。
#include <stdio.h> 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; }
このプログラムがコンパイルされると、コンパイラはソース コードをマシンコードに変換します。このマシン コードはプログラムのロジックと動作を構成し、テキスト セグメントに格納されます。
マシンコードを直接見ることはできませんが。テキストセグメントにはコンパイルされた命令が含まれていることがわかります。
基本的に、テキスト セグメントには、プログラムの実行時の動作を定義する命令が含まれています。
データセグメントは 2 つの部分に分かれています:
初期化されたデータセグメント
初期化されたデータ セグメントは、事前に初期化されたグローバル変数、外部変数、静的変数 (ローカル変数とグローバル変数の両方)、および定数グローバル変数で構成されます。初期化されたデータ セグメントには、読み取り専用 セクションと 読み取り/書き込み セクションの 2 つのセクションがあります。
変更可能な事前定義値を持つ変数、つまり初期化されたグローバル、外部、および静的 (ローカルとグローバルの両方) 変数は、読み取り/書き込み セクションに保存されます。一方、定数変数は 読み取り専用 セクションに属します。
これは、初期化されたデータ セグメント (読み取り/書き込みセクションと読み取り専用セクションの両方) に格納される変数を示す例です。
#include <stdio.h> // 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 <stdio.h> // 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; }
このプログラムでは、初期化されていない変数にはデフォルトで 0 または null 値が含まれます。これはコンパイラによる自動初期化によるものです。これは、BSS セグメントに格納されている変数の動作を示しています。
ヒープは、実行時に動的メモリ割り当てに使用されるメモリ領域です。これにより、プログラムの実行中に必要に応じてメモリを割り当てたり解放したりできます。 malloc()、calloc()、realloc()、free() などの関数は、メモリの割り当てと割り当て解除に使用されます。山の中。ヒープはプログラムのすべての部分からアクセスできます。
例:
#include <stdio.h> #include <stdlib.h> int main() { // Dynamically allocate memory for an integer variable on the heap int *ptr = (int *)malloc(sizeof(int)); return 0; }
このコード スニペットは、C での動的メモリ割り当ての簡単な使用法を示しています。メモリの要求、そのメモリへのポインタの初期化、リークを回避するためのメモリの適切な管理に関連する手順に注意を向けています。この例にはエラー処理とメモリ割り当て解除が含まれていませんが、これらは実際のアプリケーションで動的メモリを操作するための重要なコンポーネントです。
スタック セグメントの主な機能は、関数呼び出しを管理し、ローカル変数を保存することです。この部分はプログラム内のフローを制御するため、プログラムのメモリ レイアウトにおいて重要です。スタックは後入れ先出し (LIFO) 構造を採用しており、最後に追加されたデータが最初に削除されます。これにより、スタックはローカル変数とネストされた関数呼び出しの管理において非常に効率的になります。
例:
#include <stdio.h> 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; }
The code explains how stack frames store local variables. New stack frames are created by the function calls and are eliminated when the functions return. The printf instructions facilitate the visualization of each function's local variable values. The execution flow follows the calls to and returns from functions.
C programmers can improve their coding techniques and gain a better understanding of how their programs interact with memory by mastering these concepts. Understanding memory layout is a vital skill in your programming toolbox, whether you're optimizing for performance or troubleshooting a complex problem.
Feel free to follow, comment, and leave claps. Happy Coding!
Let’s connect on LinkedIn.
以上がC のメモリ レイアウトの詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。