4

重複の可能性:
c++ の文字列リテラルは静的メモリに作成されていますか?

を実行する
const char* StringPtr = "string0"と、
それは間違いなくメモリ内のどこかにあり、 のアドレスを取得できますStringPtr

しかし、私がする場合:
#define STRING0 "string0"、どこにSTRING0存在しますか?
または、コンパイラがbySTRING0の使用を置き換えるため、メモリに存在しませんか?STRING0"string0"

私の知る限り、コードに文字列を書き込むたびに、コンパイラはそれをメモリのどこかに配置する必要がありますが、その正確な動作はわかりません。
しかし、これについてはよくわかりません。

コンパイラによって操作されるように#define-ed または宣言された文字列を誰でも説明できますか?char*

また、どちらが良いですか?に#defineextern const char*または文字列extern const std::stringヘッダー ファイルに?

ありがとう!

4

5 に答える 5

5

ほとんどの場合、コンパイラは必要な場所に文字列リテラルを配置できます。リテラルがソース コードに現れるたびに 1 つのコピーが存在する場合もあれば、インスタンス間で共有される 1 つのマスター コピーが存在する場合もあります。

constこれは、同じことを意味しないC で時々問題を引き起こし、メモリを変更することが許可されています。あるプラットフォームでは同一の文字列がすべて変更されますが、別のプラットフォームでは変更が反映されません。C++11 の時点で、文字列リテラルは暗黙的に失われずconst、間違いを犯しにくくなっています。

文字列はすべてプログラムの開始前に初期化されるため、実際には実行可能なバイナリ イメージの一部になります。それくらいは確かです。

異なるのは次のとおりです。

const char StringPtr[] = "string0",

これは、一意のアドレスを持つ専用の配列オブジェクトを定義します。

于 2012-12-26T03:51:30.537 に答える
1

stringPtr は、実行可能ファイルのデータ セクションにあります。exe をテキスト エディタで開くと、検索することができます。 データセグメント

マクロは、プログラム構築の前処理段階の間だけ存在します。

コンパイラによっては、マクロ メソッドを使用すると、exe 内に同一の文字列の複数の個別のインスタンスが作成される可能性がありますが、char* メソッドを使用すると、単一のインスタンスのみを使用できます。

于 2012-12-26T03:51:33.580 に答える
1
#define STRING0

STRING0メモリに常駐しません。コンパイル中にも存在しません。PRE-compilation では、すべての出現箇所がプリプロセッサSTRING0によって「string0」に置き換えられます。この段階の後、次の段階またはコンパイルされたアプリケーションのいずれも、名前のシンボルの存在を認識しません。STRING0

const char*これが発生すると、すべてのインスタンスの多くが、コード全体で一意の文字列リテラル (ケース) になるわけではありません。これらがメモリに保存されている場所への回答は、@Potatoswatter と @silico が提供するリンクによってより適切に回答されます。

于 2012-12-26T03:45:02.507 に答える
0

#defineプリプロセッサ マクロです。コードがコンパイルされる前のプリコンパイル段階で置き換えSTRING0られます。"string0"

"string0"実行可能ファイルの静的読み取り専用メモリに常駐します。

StringPtrは変数なので、そのアドレスを取得できます。のメモリアドレスを指すだけです"string0"

于 2012-12-26T03:53:16.967 に答える
-1

を実行する#defineと、コンパイラーではなく、プリプロセスされたソースファイル内のテキストSTRING0を「string0」に置き換えてから、適切なコンパイラーに渡すプリプロセッサーがあります。

コンパイラは STRING0 を認識しませんが、STRING0 を記述したすべての場所で「string0」のみを認識します。

編集:

ソース ファイルに記述した STRING0 を置き換える "string0" の各インスタンスは、それ自体が文字列リテラルです。これらの文字列リテラルが不変であることが保証 (または宣言) されている場合、コンパイラは、この "string0" の単一のコピーを格納することでメモリ割り当てを最適化し、他の用途をそのコピーに向けることができます (編集でこの段落を言い換えました)。

(編集:これらの同一のリテラル文字列定数は、単一のコピーにマージされる可能性がありますが、これはコンパイラ次第です。標準はそれを要求または強制しません:http://www.velocityreviews.com/forums/t946521-merging- c-std.html によって保証された文字列リテラル

最後の質問については、最も移植性が高いのは、次のように宣言することです。const char *

後で編集:これまでに見つけた文字列リテラルに関する最良の議論はここにあります: https://stackoverflow.com/a/2245983/1284631

また、静的配列の内容が上書きされる可能性があるため、文字列リテラルが他のコピーとマージできない場合、静的に割り当てられた char 配列の初期化にも使用できることに注意してください。以下の例を参照してください。2 つの同一の文字列リテラル "hello" はマージできません。

#include <stdio.h>
#include <string.h>

int main(){

        char x[50]="hello";

        printf("x=%s, &x[0]=%p\n",x,&x[0]);

        const char *y="hello";

        printf("y=%s, &y[0]=%p\n",y,&y[0]);

        strcpy(&x[0],"zz");

        printf("x=%s, &x[0]=%p\n",x,&x[0]);

        return 0;
}

このコードの出力は次のとおりです。

x=hello, &x[0]=0x7fff8a964370
y=hello, &y[0]=0x400714
x=zz, &x[0]=0x7fff8a964370
于 2012-12-26T03:45:52.810 に答える