「労働者が自分の仕事をうまくやりたいなら、まず自分の道具を研ぎ澄まさなければなりません。」 - 孔子、「論語。陸霊公」
表紙 > プログラミング > C のメモリ レイアウト

C のメモリ レイアウト

2024 年 8 月 17 日に公開
ブラウズ:748

導入

メモリ レイアウトとは、コンピュータのメモリがどのように編成および構造化されているかを指します。これは、さまざまなシステム コンポーネントによってメモリがどのように分割され、利用されるかを定義します。

これは、実行中に変数、関数、データ構造がどのように保存され、アクセスされるかに直接影響するため、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;
}

このプログラムのコンパイル時に、コンパイラはソース コードをマシン コードに変換します。このマシン コードはプログラムのロジックと動作を構成し、テキスト セグメントに格納されます。

マシンコードを直接見ることはできません。テキストセグメントにはコンパイルされた命令が含まれていることがわかります。

基本的に、テキスト セグメントには、プログラムの実行時の動作を定義する命令が含まれています。

データセグメント

データ セグメントは 2 つの部分に分かれています:

  • 初期化されたデータセグメント
  • 初期化されていないデータセグメント

初期化されたデータ セグメント

初期化されたデータ セグメントは、事前に初期化されたグローバル変数、外部変数、静的変数 (ローカル変数とグローバル変数の両方)、および定数グローバル変数で構成されます。初期化されたデータ セグメントには、読み取り専用 セクションと 読み取り/書き込み セクションの 2 つのセクションがあります。

変更可能な定義済みの値を持つ変数、つまり初期化されたグローバル、外部、および静的 (ローカルとグローバルの両方) 変数は、読み取り/書き込み セクションに保存されます。一方、定数変数は 読み取り専用 セクションに属します。

これは、初期化されたデータ セグメント (読み取り/書き込みセクションと読み取り専用セクションの両方) に格納される変数を示す例です。

#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;
}

このプログラムでは、初期化されていない変数にはデフォルトで 0 または null 値が含まれます。これはコンパイラによる自動初期化によるものです。これは、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] に連絡して削除してください。
最新のチュートリアル もっと>

免責事項: 提供されるすべてのリソースの一部はインターネットからのものです。お客様の著作権またはその他の権利および利益の侵害がある場合は、詳細な理由を説明し、著作権または権利および利益の証拠を提出して、電子メール [email protected] に送信してください。 できるだけ早く対応させていただきます。

Copyright© 2022 湘ICP备2022001581号-3