グローバル変数、ローカル変数、ヒープ、スタックなどの概念と、C言語プログラムでのメモリアドレス割り当て


1つ、C言語のメモリ割り当て

1つは、メモリ割り当て
1 、メモリ割り当てのタイプ:

C / C ++では、メモリはスタック領域、ヒープ領域、グローバル/静的ストレージ領域、定数ストレージ領域、およびコード領域の5つの領域に分割されます。

静的メモリ割り当て:コンパイル時に割り当てられます。含む:グローバル、静的グローバル、静的ローカルの3つの変数。

動的メモリ割り当て:実行時の割り当て。含む:スタック(スタック):ローカル変数。ヒープ:c言語で使用される変数は、メモリに動的に割り当てられます。(mallocまたはcalloc、realloc、free関数)

2.変数のメモリ割り当て:

スタック領域(スタック):必要なときにコンパイラによって割り当てられ、不要なときに自動的にクリアされる変数が格納されるストレージ領域を指します。たとえば、関数が実行されると、関数の正式なパラメータとローカル変数が関数はスタック領域に割り当てられます。操作が終了すると、仮パラメータとローカル変数がスタックから削除されます(自動的に解放されます)。スタックメモリ割り当て操作は、プロセッサの命令セットに組み込まれています。これは効率的ですが、割り当てられるメモリスペースは限られています。

ヒープ領域(ヒープ):プログラマーが手動で割り当てて解放するストレージ領域を指します。プログラマーがこのメモリーを解放しない場合、プログラムが実行されるまでメモリーは常に占有されます。システムは自動的にそれを回復します。MallocはC言語で使用され、アプリケーションは無料です。また、スペースを解放します。

静的ストレージ領域(静的):グローバル変数と静的変数のストレージがまとめられます。初期化されたグローバル変数と静的変数は同じ領域にあります。このスペースは、プログラムの実行時にシステムによって解放されます。

定数格納領域(const):定数文字列はここに格納されます。たとえば、「ABC」文字列は定数領域に格納され、読み取り専用および書き込み不可の文字列は定数領域に格納されます。constで変更されたグローバル変数も定数領域に格納され、constで変更されたローカル変数は引き続きスタックにあります。

プログラムコード領域:ソースプログラムのバイナリコードを格納します。

元のテキストは次のとおりです
。C言語:メモリ割り当て


2.ubuntuシステムでのプログラミングと検証のための情報の出力

コードソース:C言語では、ローカル変数、グローバル変数、静的変数、ヒープ、およびスタックのメモリアドレスが
1.cファイルを作成し、コードを記述します。

#include <stdio.h>
#include <string.h>
#include <stdlib.h>
 
void before()
{
    
    
 
}
 
char g_buf[16];
char g_buf2[16];
char g_buf3[16];
char g_buf4[16];
char g_i_buf[]="123";
char g_i_buf2[]="123";
char g_i_buf3[]="123";
 
void after()
{
    
    
 
}
 
int main(int argc, char **argv)
{
    
    
        char l_buf[16];
        char l_buf2[16];
        char l_buf3[16];
        static char s_buf[16];
        static char s_buf2[16];
        static char s_buf3[16];
        char *p_buf;
        char *p_buf2;
        char *p_buf3;
 
        p_buf = (char *)malloc(sizeof(char) * 16);
        p_buf2 = (char *)malloc(sizeof(char) * 16);
        p_buf3 = (char *)malloc(sizeof(char) * 16);
 
        printf("g_buf: 0x%x\n", g_buf);
        printf("g_buf2: 0x%x\n", g_buf2);
        printf("g_buf3: 0x%x\n", g_buf3);
        printf("g_buf4: 0x%x\n", g_buf4);
 
        printf("g_i_buf: 0x%x\n", g_i_buf);
        printf("g_i_buf2: 0x%x\n", g_i_buf2);
        printf("g_i_buf3: 0x%x\n", g_i_buf3);
 
        printf("l_buf: 0x%x\n", l_buf);
        printf("l_buf2: 0x%x\n", l_buf2);
        printf("l_buf3: 0x%x\n", l_buf3);
 
        printf("s_buf: 0x%x\n", s_buf);
        printf("s_buf2: 0x%x\n", s_buf2);
        printf("s_buf3: 0x%x\n", s_buf3);
 
        printf("p_buf: 0x%x\n", p_buf);
        printf("p_buf2: 0x%x\n", p_buf2);
        printf("p_buf3: 0x%x\n", p_buf3);
 
        printf("before: 0x%x\n", before);
        printf("after: 0x%x\n", after);
        printf("main: 0x%x\n", main);
 
        if (argc > 1)
        {
    
    
                strcpy(l_buf, argv[1]);
        }
        return 0;
}

1.cをコンパイルして実行します

gcc 1.c -o 1
./1

ここに画像の説明を挿入します
ここに画像の説明を挿入します
上の図によると、メモリアドレスはすべて

詳細については、
C / C ++プログラムメモリのさまざまな変数ストレージ領域と各領域の詳細な説明を参照してください
。C言語では、ローカル変数、グローバル変数、静的変数、ヒープ、およびスタックのメモリアドレス
。Cのキーワードvolatile言語が問題の根源です。

3、stm32システム検証

以前のシリアル通信コードを使用して、main.cを次のように変更します。

#include "stm32f10x.h"
#include "bsp_usart.h"

char quanju1[16];
char quanju2[16];
char quanju3[16];
	
int main(void)
{
    
    	
	char bufen1[16];
  char bufen2[16];
  char bufen3[16];

  USART_Config();

  printf("bufen1: 0x%p\n", bufen1);
  printf("bufen2: 0x%p\n", bufen2);
  printf("bufen3: 0x%p\n", bufen3);
	 
  printf("quanju1: 0x%p\n", quanju1);
  printf("quanju2: 0x%p\n", quanju2);
  printf("quanju3: 0x%p\n", quanju3);
  while(1)
	{
    
    	
		
	}	
}

16進ファイルの生成
ここに画像の説明を挿入します
前のシリアル通信と同じ手順に従い、stm32ボードのリセットボタンをクリックすると、次の図が表示されます。

ここに画像の説明を挿入します
main.cコードを次のように変更し続けます。

#include "stm32f10x.h"
#include "bsp_usart.h"
#include <stdlib.h>

int main(void)
{
    
    	
  static char m1[16];
  static char m2[16];
  static char m3[16];
  char *n1;
  char *n2;
  char *n3;

 
  USART_Config();

  printf("m1: 0x%p\n", m1);
  printf("m2: 0x%p\n", m2);
  printf("m3: 0x%p\n", m3);
	 
  n1 = (char *)malloc(sizeof(char) * 16);
  n2 = (char *)malloc(sizeof(char) * 16);
  n3 = (char *)malloc(sizeof(char) * 16);
	
  printf("n1: 0x%p\n", n1);
  printf("n2: 0x%p\n", n2);
  printf("n3: 0x%p\n", n3);
  while(1)
	{
    
    	
		
	}	
}

16進ファイルをコンパイルして生成します。
ここに画像の説明を挿入します
シリアルポートのデバッグで
ここに画像の説明を挿入します
は、シリアルポートのデータに基づいて、ハイメモリアドレスからローメモリアドレスまでを認識します。スタック領域、ヒープ領域、グローバル領域(静的領域)、定数領域、コード領域が順番に分散されます。図に示すように、グローバルエリアの上位アドレスは.bssセクションで配布され、下位アドレスは.dataセクションで配布されます。詳細について
ここに画像の説明を挿入します
は、以下を参照してください。
[IoT] STM32メモリ割り当て
ベースの詳細な説明STM32分析スタック、ヒープ、グローバルエリア、定数エリア、コードエリア、RAM、ROM
STM32KEILスタック設定

おすすめ

転載: blog.csdn.net/aiwr_/article/details/110431441