0

次の行動の理由を自分で説明することはできません。1 つは char* として、もう 1 つは char[] として 2 つのテキストを初期化し、それらを構造体に入れます。どちらも構造では問題ないように見えますが、メインに戻ると、2 番目のものが失われ、最初のコンパイラ警告が表示されますが、これは理解できます (文字列定数から char* への非推奨の変換)。

これは私がここで尋ねる最初の質問であり、間違ったことをお詫び申し上げます。はい、検索しようとしましたが、char* と char[] に関連して、多くの Q&A が表示されますが、私が抱えているネストされた問題に似たものはありません。

添付のコードから、次の出力が得られます。

get_struct: 5 test test2
main: 5 test

(最後のtest2がありません)

だからコード:

    #include <iostream> 

    typedef struct {
        double a_double;
        char* a_char1;
        char* a_char2;
    } testStruct;

    testStruct make_struct(double d, char* c1, char* c2) {          
        testStruct t;

        t.a_double = d;
        t.a_char1 = c1;
        t.a_char2 = c2;

        return t;
    }

    void get_struct(testStruct &t) {    
        char* test_char1 = "test";
        char test_char2[] = "test2";
        double test_double = 5;

        t = make_struct(test_double, test_char1, test_char2);

        std::cout << "get_struct: " << t.a_double << " " 
            << t.a_char1 << " " << t.a_char2  << std::endl;
    }

    int main() {
        testStruct t;
        get_struct(t);
        std::cout << "main: " << t.a_double << " " 
            << t.a_char1 << " " << t.a_char2 << std::endl;
        return 0;
    }
4

3 に答える 3

3

ローカル変数へのポインターを構造体に格納するという問題があります。

配列の場合、関数が戻るtest_char2と存在しなくなります。get_structこれは、ポインターa_char2が有効な文字列を指しなくなったことを意味し、このポインターの逆参照は未定義の動作です。

最初のポインターが機能する理由は、それがローカル変数を指しておらず、文字列リテラルを指しており、それらがメモリの別の場所に格納されているためです。

C++ でコーディングする場合、文字列にポインターや配列を使用する理由はなくなり、代わりにstd::stringクラスを使用します。

于 2013-09-04T14:45:04.537 に答える
2
char* test_char1 = "test";

これにより、文字列リテラルへのポインターが作成されます。文字列リテラルはありますconstが、歴史的な理由から、言語ではポインターを非にすることができますconst。ただし、これは非推奨であるため、警告が表示されます。文字列を変更しようとすると、未定義の動作が発生します。

char test_char2[] = "test2";

これにより、文字列リテラルをコピーして初期化されたローカル配列が作成されます。ではありませんconstので、お好みで変更してください。ただし、関数が返されると、これは破棄されるため、構造体は無効なメモリへのぶら下がりポインターになります。で印刷しようとすると、未定義の動作が発生するのはそのためですmain

2 つのアドバイス:

  • C スタイルの文字配列とポインターを使用して文字列を表現しないでください。使用してstd::stringください。これにより、メモリが管理され、ここで発生している生涯の問題が回避されます。
  • 配列やポインターを本当にいじりたい場合は、const char*実際に変更する必要がない限り使用してください。そうしないと、文字列リテラルを扱うのが難しくなります。
于 2013-09-04T14:54:45.277 に答える
1

文字列リテラルをローカルchar[]変数に割り当てると、そのストレージはローカルに割り当てられます。

そのスコープからそのポインターをエクスポートすると、ローカル変数の (自動) ストレージ期間の制約に違反し、ポインターの背後にあるメモリにアクセスすることは未定義の動作です。

対照的に、 に割り当てるとchar*、静的に割り当てられた文字列へのポインターが作成され、ローカル ストレージへのコピーは行われません。したがって、ポインターはそのスコープ外でも有効なままです。

于 2013-09-04T14:46:31.270 に答える