0

私は最近、ポインターを使用して c の定数の値を変更することは可能ですが、文字列リテラルでは不可能であることを知りました。おそらく説明は、定数やその他の文字列がスペース内の変更可能な領域にスペースが割り当てられているのに対し、文字列リテラルはスペース内の変更不可能な領域(おそらくコードセグメント)にあるという事実にあります。これらの変数のアドレスを表示するプログラムを作成しました。出力も表示されます。

#include <stdio.h>
int x=0;
int y=0;

int main(int argc, char *argv[])
{
    const int a =5;
    const int b;
    const int c =10;
    const char *string = "simar";   //its a literal, gets space in code segment
    char *string2 = "hello";
    char string3[] = "bye"; // its array, so gets space in data segment
    const char string4[] = "guess";
    const int *pt;
    int *pt2;

    printf("\nx:%u\ny:%u Note that values are increasing\na:%u\nb:%u\nc:%u Note that values are dec, so they are on stack\nstring:%u\nstring2:%u Note that address range is different so they are in code segment\nstring3:%u Note it seems on stack as well\nstring4:%u\n",&x,&y,&a,&b,&c,string,string2,string3,string4); 
}

ここに画像の説明を入力

これらの変数がスペースを取得する場所を正確に説明してください?? グローバルはどこでスペースを取得し、定数はどこで取得し、文字列リテラルはどこで取得しますか??

4

2 に答える 2

5

「可能性がある」は、そのケースを誇張しています。

const オブジェクトを変更しようとするコードを作成できます (たとえば、そのアドレスを非 const 型へのポインターにキャストすることによって)。文字列リテラルを変更しようとするコードを書くこともできます。

どちらの場合も、コードには未定義の動作があります。つまり、標準は何が起こるかを気にしません。実装は好きなことをすることができ、何が起こるかは通常、重要な何かの偶発的な副作用です。振る舞いに頼ることはできません。要するに、そのコードは間違っています。これは、 として定義されたオブジェクトconstと文字列リテラルの両方に当てはまります。

特定の実装では、結果としてオブジェクトまたはリテラルが変更される場合があります。別の実装では、アクセス エラーが発生してプログラムがクラッシュする可能性があります。3 番目の実装では、1 つの動作が発生する場合と、別の場合に別の動作が発生する場合があります。まったく違うことが起こるかもしれません。

変数がスペースを取得する場所は実装固有ですが、一般的な実装では次のようになります。

  • xy変更可能なデータ セグメント内にある
  • aスタックにあります。そのアドレスを取得するという事実がなければ、変数ストレージは完全に最適化5され、値は、コンパイラが使用するコードに対して発行するすべての CPU 命令で即値として使用される可能性がありますa
  • bエラーだと思います - 初期化されていない const オブジェクトです。許可されている可能性がありますが、コンパイラはおそらく警告する必要があります。
  • cと同じように、スタックにありますa
  • リテラル「simar」などはすべて、実装がrodataを気にしない場合、コードセグメント、読み取り専用データセグメント、または変更可能なデータセグメントのいずれかにあります。
  • string3およびstring4はスタック上の配列です。それぞれは、文字列リテラルの内容をコピーすることによって初期化されます。
于 2012-08-15T12:04:59.200 に答える
1

私は最近、ポインターを使用して c の定数の値を変更できることを知りました。

これを行うと、未定義の動作 (標準 6.7.3 を参照) につながります。つまり、何でも起こり得るということです。実際には、一部の RAM ベースのシステムでは定数を変更できます。

文字列リテラルでは不可能

これも同様に未定義の動作であり、動作する場合も動作しない場合もあり、ハードドライブから青い煙が立ち上る原因となる場合もあります。

おそらく説明は、定数やその他の文字列が空間内の変更可能な領域に割り当てられているのに対し、文字列リテラルは空間内の変更不可能な領域にあるという事実にあります

これはシステムに依存します。一部のシステムでは、それらは両方とも定数/仮想 RAM セグメントにあり、一部のシステムでは、不揮発性フラッシュ メモリにある可能性があります。どのシステムについて話しているかを特定せずに、物事がメモリ内のどこに行き着くかについて議論しても意味がありません。一般的なケースはありません。

于 2012-08-15T12:02:01.037 に答える