1

一部のポインタの仕組みが理解できません。私はいつも、ポインタ変数 (p) を作成したとき、その領域を malloc する (p = malloc(x)) か、または別の変数のアドレス (p = &a)

ただし、このコードでは、最初の割り当ては一貫して機能しますが、最後の割り当てはセグメンテーション違反を引き起こします。

typedef struct
{
    int value;
} test_struct;

int main(void)
{
    //This works
    int* colin;
    *colin = 5;

    //This never works
    test_struct* carter;
    carter->value = 5;
}

colin が予備のメモリを指していないのに、最初のものはなぜ機能するのですか? そして、なぜ2番目は機能しないのですか?

これもCで書いていますが、C++の知識がある人なら答えられるはずです。

編集:わかりました、最初のものも機能しないはずですが、なぜ機能しますか. それが私が求めているものです。

4

4 に答える 4

7
// This works
int* colin;
*colin = 5;

未定義の動作へようこそ: クラッシュしないという事実は、動作することを意味しません。初期化されていないポインターへのアクセスは常に間違っていますが、クラッシュしない場合もあります。

スペースをmallocするか、別の変数のアドレスに設定しない限り、参照して割り当てることはできませんでした

正解です。一般に、ポインタはプログラムに割り当てられた場所を指す必要があります。それを行うには複数の方法がありますが、それらはすべて、説明した2つのシナリオのいずれかに要約されます.ポインターは、動的に割り当てられたメモリ(つまりmalloc)または静的に割り当てられたメモリ(つまり、変数)。

于 2013-06-25T10:17:39.727 に答える
1

私はいつも、ポインタ変数 (p) を作成したとき、その領域を malloc する (p = malloc(x)) か、または別の変数のアドレス (*p = &a)

Cには許可されていないものがあるため、Cコンパイラはエラーを発行してプログラムのコンパイルを拒否します.C標準では動作が定義されていない他のものがあるため、実装が何を行うかについての制約はありません. do ... これの理由は、実装方法に大きな自由度を与え、非常に高速なコードを生成できるようにするためです。これは、プログラマーを自分のエラーから保護することに大きな価値を置く、より現代的な言語とは異なります。結果として、有効なコードを記述するプログラマーの負担が大きくなります。

あなたのコードは、動作が未定義の例です。コンパイラは、p逆参照して代入するときに の値が有効かどうかを確認するチェックを生成しません...ジャンクが含まれている可能性があり、ストアはメモリ内の任意の場所にある可能性があります。または、アクセスできないメモリを指している可能性があり、ストアはクラッシュします (動作が定義されていないため、他の可能性もありますが、これらは一般的な現実世界の実装で発生するものです)。コードが 1 つのストアでクラッシュしたが、他のストアではクラッシュしなかったというのは、純粋な偶然であり、実装の細部のアーティファクトです... 異なるコンパイラ、異なるバージョンのコンパイラ、ソースへのわずかな変更...これらのいずれかたまたま入っていた値を変更することで、物や他のものが結果を変える可能性がありますp...スタック変数であるため、スタックに残された任意の値p(C言語標準はスタックを義務付けておらず、言及さえしていませんが、一般的な実世界の実装autoではスタックに変数を割り当てます。)

肝心なのは、ご存知のように、「許可」されていたとしても、あなたのプログラムは間違っているということです。R. Martinho Fernandes がコメントで述べたように、最初のストアが「機能した」ことは不運です...商用製品で、その「機能」のようなものを持つことは、いつでも失敗する可能性があるため、非常に不幸です。考えられる最悪の状況。ここでは C 言語は役に立ちません。非常に訓練する必要があります。

于 2013-06-25T10:34:04.737 に答える