4

私は次のコードを持っています:

#include <iostream>
using namespace std;
int main()
{
    char* a = "foo";
    char* b = "bar";
    a = b;
    cout << a << ", " << b << endl;
    return 0;
}

これはコンパイルして動作します。印刷しbar, barます。ここで、ここで行われているのは文字列のコピーではないことを示したいと思います。b私は変化し、それも変化することを示したいと思いaます。私はこの簡単なコードを思いつきました:

#include <iostream>
using namespace std;
int main()
{
    char* a = "foo";
    char* b = "bar";
    a = b;
    b[1] = 'u'; // ← just this line added
    cout << a << ", " << b << endl;
    return 0;
}

...しかし、それはセグメンテーション違反です。なんで?興味深いことに、次の変更は問題なく実行されます。

#include <iostream>
using namespace std;
int main()
{
    char* a = "foo";
    char b[] = "bar"; // ← declaration changed here
    a = b;
    b[1] = 'u';
    cout << a << ", " << b << endl;
    return 0;
}

前のようにセグメンテーション違反にならないのはなぜですか? ポインター スタイルと配列スタイルの文字列初期化の間に重要な違いがいくつか欠けていると思います。

4

6 に答える 6

9

文字列定数は変更できません。これは、最初のコード サンプルのように、ポインターからリテラルへの構文を使用した場合に得られるものです。

この質問も参照してください: c++ の文字列リテラルは静的メモリに作成されますか? .

于 2009-03-05T09:33:37.060 に答える
6

これを書くとき:

char *b = "bar";

コンパイラは、匿名 (名前のない) メモリ領域を割り当てて、文字列リテラル "bar" を格納します。文字列リテラルは変更できないため、コンパイラは (リンカーとオペレーティング システムの助けを借りて) 文字列リテラルを実行中のプログラムの書き込み保護されたメモリ空間の一部に配置します。変更しようとすると、オペレーティング システムがそれをキャッチし、プログラムにセグメンテーション違反が発生します。

(あなたのコードは C ではなく C++ ですが、それはこの質問には関係ありません。)

于 2009-03-05T09:34:41.050 に答える
2

あなたが書くとき:

char *foo = "bar";

実際には、「バー」がメモリの読み取り専用セグメントに格納されます。したがって、それは不変です。読み取り専用セグメントを変更しようとすると、segfault が発生します。

于 2009-03-05T09:35:07.757 に答える
2

ポインターの値を出力することで、「a」が変更されたことを示すこともできます。

#include <iostream>
using namespace std;
int main()
{
    char* a = "foo";
    char* b = "bar";
    a = b;

    cout << (void*)a << ", " << (void*)b << endl;
}

これにより、「a」と「b」が指すアドレスが出力されます。
'void*' にキャストする必要があります。これは、演算子 << が文字列を出力するために 'char*' に対してオーバーロードされているためです。他のポインターはアドレスを出力します。

于 2009-03-05T09:43:52.213 に答える
1

理論的には、文字列リテラルを char* に割り当てることはできず、'const char*' のみに割り当てる必要があります。その後、コンパイラは、seg faulting コードを記述する前に停止します。

于 2009-03-05T11:44:33.500 に答える
-1

この違いはおそらくコンパイラ固有のものです。あなたの要点を示すために、malloc を使用してバッファを割り当ててから、文字列をこのバッファにコピーします。文字列が不要になったら free を使用することを忘れないでください。

于 2009-03-05T09:34:58.117 に答える