C言語の文字列定数はいったいどこにあるのか.
5028 ワード
定数ストレージローカル変数、静的ローカル変数、グローバル変数、グローバル静的変数、文字列定数、および動的購買依頼をまとめるメモリ領域
1、ローカル変数がスタックに格納される2、グローバル変数、静的変数(グローバルおよびローカル静的変数)が静的記憶領域3、new出願のメモリがスタックに格納される4、文字列定数も静的記憶領域に格納される
補足:1、スタック内の変数メモリは、定義された区間の終了に伴って自動的に解放されます.スタックの場合、手動freeが必要です.そうしないと、プログラムが終わるまで存在します.2、静的記憶領域の場合、変数定数はプログラムの実行中にずっと存在し、解放されず、変数定数はその中にコピーが1部しかなく、同じ変数と定数の異なるコピーは現れない.
=====================================================================================
char *c="zhouming"; 本によると、「zhouming」という文字列は定数として扱われ、このプログラムのメモリ静的領域に置かれている.cは文字型ポインタであり、局所変数であればスタック内に格納され、そのポインタ変数にはアドレスが格納され、
このアドレスは、文字列の最初のアルファベットZのアドレスである.
printf()出力を使用すると、フォーマット時に%sを選択するとzhoumingが出力されます.これはprintfが末尾記号'0'に遭遇して印刷を停止することです.
文字列「zhouming」は定数で、連続したメモリに格納され、末尾に文字列の終了を表す末尾文字があります.
一般的なint i=1;
文字列定数を変更する必要が少ないため、すべての文字定数は静的メモリ領域に配置されます.静的メモリ領域に配置すると効率が向上します.
例:
char str1[] = "abcd"; char str2[] = "abcd";
const char str3[] = "abcd"; const char str4[] = "abcd";
const char *str5 = "abcd"; const char *str6 = "abcd";
char *str7 = "abcd"; char *str8 = "abcd";
cout << ( str1 == str2 ) << endl; cout << ( str3 == str4 ) << endl; cout << ( str5 == str6 ) << endl; cout << ( str7 == str8 ) << endl;
その結果、0 0 1 str 1、str 2、str 3、str 4は配列変数であり、それぞれのメモリ空間がある.文字配列はローカル変数としてスタック領域に格納される.str 5,str 6,str 7,str 8はポインタであり、同じ定数領域を指している.「abcd」は静的データ領域に格納され、グローバルであり、
問題の導入:次のプログラムの出力を見てください.
#include char *returnStr() { char *p="hello world!"; return p; } int main(){char*str=NULL;//必ず初期化し、str=returnStr();printf("%s",str);
return 0; }
これは何の問題もありません.「hello world!」静的データ領域に格納された文字列定数であり、その文字列定数が格納された静的データ領域のヘッダアドレスをポインタに付与しているため、returnStr関数が終了すると、その文字列定数が存在するメモリが回収されないため、ポインタによるスムーズなアクセスが可能となる.
しかし、以下に問題がある:#include char *returnStr() { char p[]="hello world!"; return p; } int main(){char*str=NULL;//必ず初期化し、str=returnStr();printf("%s",str);
return 0; }
"hello world!"静的データ領域に格納された文字列定数です.間違いありませんが、スタックに格納されたローカル変数(char[]型配列)に文字列定数を割り当てます.これにより、2つのコンテンツと同じメモリ、すなわち「char p[]=「hello world!」;この文は「hello world!」この文字列はメモリに2つのコピーがあり、1つは動的に割り当てられたスタックにあり、もう1つは静的ストレージ領域にある.これは前者と最も本質的な違いであり,returnStr関数が終了するとスタックが空になり,局所変数のメモリも空になるので,このときの関数は解放されたメモリアドレスを返すので,印刷されたのは乱符号である.
関数の戻り値がローカル変数のアドレスでない場合は、そのローカル変数はstaticタイプとして明記する必要があります.次のようになります.
staticは主に範囲を限定するために使われています.
#include char *returnStr() { static char p[]="hello world!"; return p; } int main() { char *str=NULL; str=returnStr(); printf("%s", str);
return 0; }
この問題は次の例でよりよく説明できます.
#include//は、動的データ領域、スタックに位置するローカル変数のアドレスを返します.
char*s 1(){char*p 1=“qqq”;//“char p[]=“Hello world!”をテストするためにの文字列が静的記憶領域にもコピーchar p[]=「Hello world!」;char* p2 = "w";//‘char p[]=“Hello world!”をテストするためにの文字列が静的記憶領域にもprintf(「in s 1 p=%p」,p)のコピーがあるかどうか.printf("in s1 p1=%p", p1); printf("in s1: string's address: %p", &("Hello world!")); printf("in s1 p2=%p", p2); return p; }
//静的データ領域にある文字列定数のアドレスを返します
char *s2() { char *q="Hello world!"; printf("in s2 q=%p", q); printf("in s2: string's address: %p", &("Hello world!")); return q; }
//静的ローカル変数のアドレスを返します.このアドレスは静的データ領域にあります.
char *s3() { static char r[]="Hello world!"; printf("in s3 r=%p", r); printf("in s3: string's address: %p", &("Hello world!")); return r; }
int main() { char *t1, *t2, *t3; t1=s1(); t2=s2(); t3=s3();
printf("in main:"); printf("p=%p, q=%p, r=%p", t1, t2, t3);
printf("%s", t1); printf("%s", t2); printf("%s", t3);
return 0; }
出力結果の実行:
in s1 p=0013FF0C in s1 p1=00431084 in s1: string's address: 00431074 in s1 p2=00431070 in s2 q=00431074 in s2: string's address: 00431074 in s3 r=00434DC0 in s3: string's address: 00431074 in main:p=0013FF0C, q=00431074, r=00434DC0 $ Hello world! Hello world!
この結果は、上記の説明を裏付けるとともに、文字列定数を定数と呼ぶのは、名前のない文字列として定数と見なし、静的データ領域に格納できるためであると結論した.ここでいう静的データ領域は,スタック,スタックなどの動的データ領域に対してである.静的データ領域にはグローバル変数と静的変数が格納されています.この点から、文字列定数は「Hello world!」という名前のない静的変数とも呼ばれます.この文字列は関数s 1およびs 2で参照されているが、メモリにはコピーが1部しかなく、静的変数の性質に相当する.
もう一つの実験があります
実験結果は次のとおりです.
428227212449842822724282272任意のキーを押して続行してください.
ところで、文字定数‘a’
sizeof(‘a’)は4であり、1文字長である.
1、ローカル変数がスタックに格納される2、グローバル変数、静的変数(グローバルおよびローカル静的変数)が静的記憶領域3、new出願のメモリがスタックに格納される4、文字列定数も静的記憶領域に格納される
補足:1、スタック内の変数メモリは、定義された区間の終了に伴って自動的に解放されます.スタックの場合、手動freeが必要です.そうしないと、プログラムが終わるまで存在します.2、静的記憶領域の場合、変数定数はプログラムの実行中にずっと存在し、解放されず、変数定数はその中にコピーが1部しかなく、同じ変数と定数の異なるコピーは現れない.
=====================================================================================
char *c="zhouming"; 本によると、「zhouming」という文字列は定数として扱われ、このプログラムのメモリ静的領域に置かれている.cは文字型ポインタであり、局所変数であればスタック内に格納され、そのポインタ変数にはアドレスが格納され、
このアドレスは、文字列の最初のアルファベットZのアドレスである.
printf()出力を使用すると、フォーマット時に%sを選択するとzhoumingが出力されます.これはprintfが末尾記号'0'に遭遇して印刷を停止することです.
文字列「zhouming」は定数で、連続したメモリに格納され、末尾に文字列の終了を表す末尾文字があります.
一般的なint i=1;
文字列定数を変更する必要が少ないため、すべての文字定数は静的メモリ領域に配置されます.静的メモリ領域に配置すると効率が向上します.
例:
char str1[] = "abcd"; char str2[] = "abcd";
const char str3[] = "abcd"; const char str4[] = "abcd";
const char *str5 = "abcd"; const char *str6 = "abcd";
char *str7 = "abcd"; char *str8 = "abcd";
cout << ( str1 == str2 ) << endl; cout << ( str3 == str4 ) << endl; cout << ( str5 == str6 ) << endl; cout << ( str7 == str8 ) << endl;
その結果、0 0 1 str 1、str 2、str 3、str 4は配列変数であり、それぞれのメモリ空間がある.文字配列はローカル変数としてスタック領域に格納される.str 5,str 6,str 7,str 8はポインタであり、同じ定数領域を指している.「abcd」は静的データ領域に格納され、グローバルであり、
問題の導入:次のプログラムの出力を見てください.
#include
return 0; }
これは何の問題もありません.「hello world!」静的データ領域に格納された文字列定数であり、その文字列定数が格納された静的データ領域のヘッダアドレスをポインタに付与しているため、returnStr関数が終了すると、その文字列定数が存在するメモリが回収されないため、ポインタによるスムーズなアクセスが可能となる.
しかし、以下に問題がある:#include
return 0; }
"hello world!"静的データ領域に格納された文字列定数です.間違いありませんが、スタックに格納されたローカル変数(char[]型配列)に文字列定数を割り当てます.これにより、2つのコンテンツと同じメモリ、すなわち「char p[]=「hello world!」;この文は「hello world!」この文字列はメモリに2つのコピーがあり、1つは動的に割り当てられたスタックにあり、もう1つは静的ストレージ領域にある.これは前者と最も本質的な違いであり,returnStr関数が終了するとスタックが空になり,局所変数のメモリも空になるので,このときの関数は解放されたメモリアドレスを返すので,印刷されたのは乱符号である.
関数の戻り値がローカル変数のアドレスでない場合は、そのローカル変数はstaticタイプとして明記する必要があります.次のようになります.
staticは主に範囲を限定するために使われています.
#include
return 0; }
この問題は次の例でよりよく説明できます.
#include
char*s 1(){char*p 1=“qqq”;//“char p[]=“Hello world!”をテストするためにの文字列が静的記憶領域にもコピーchar p[]=「Hello world!」;char* p2 = "w";//‘char p[]=“Hello world!”をテストするためにの文字列が静的記憶領域にもprintf(「in s 1 p=%p」,p)のコピーがあるかどうか.printf("in s1 p1=%p", p1); printf("in s1: string's address: %p", &("Hello world!")); printf("in s1 p2=%p", p2); return p; }
//静的データ領域にある文字列定数のアドレスを返します
char *s2() { char *q="Hello world!"; printf("in s2 q=%p", q); printf("in s2: string's address: %p", &("Hello world!")); return q; }
//静的ローカル変数のアドレスを返します.このアドレスは静的データ領域にあります.
char *s3() { static char r[]="Hello world!"; printf("in s3 r=%p", r); printf("in s3: string's address: %p", &("Hello world!")); return r; }
int main() { char *t1, *t2, *t3; t1=s1(); t2=s2(); t3=s3();
printf("in main:"); printf("p=%p, q=%p, r=%p", t1, t2, t3);
printf("%s", t1); printf("%s", t2); printf("%s", t3);
return 0; }
出力結果の実行:
in s1 p=0013FF0C in s1 p1=00431084 in s1: string's address: 00431074 in s1 p2=00431070 in s2 q=00431074 in s2: string's address: 00431074 in s3 r=00434DC0 in s3: string's address: 00431074 in main:p=0013FF0C, q=00431074, r=00434DC0 $ Hello world! Hello world!
この結果は、上記の説明を裏付けるとともに、文字列定数を定数と呼ぶのは、名前のない文字列として定数と見なし、静的データ領域に格納できるためであると結論した.ここでいう静的データ領域は,スタック,スタックなどの動的データ領域に対してである.静的データ領域にはグローバル変数と静的変数が格納されています.この点から、文字列定数は「Hello world!」という名前のない静的変数とも呼ばれます.この文字列は関数s 1およびs 2で参照されているが、メモリにはコピーが1部しかなく、静的変数の性質に相当する.
もう一つの実験があります
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
int main()
{
char *b;
char *c;
char a[]="chenhuijie";
b="chenhuijie";
c="chenhuijie";
printf("%d,%d,%d,%d
",b,a,c,&("chenhuijie"));
}
実験結果は次のとおりです.
428227212449842822724282272任意のキーを押して続行してください.
ところで、文字定数‘a’
sizeof(‘a’)は4であり、1文字長である.