2009-07-11 5 views
1

次のコード:別のCポインタ質問

int *a; 
*a = 5; 

最も可能性の高いセグメンテーションフォールトでの結果と私は理由を知っているだろう。

次のコード:

int a; 
*a = 5; 

もコンパイルされません。 (gcc:unary *の型引数が無効です)。

次に、ポインタは、単にアドレスを格納するため 使用される整数です。 私が言うのであれば、なぜそれが問題にする必要があります:

*a = 5; 

理想的には、これはまた、セグメンテーションフォールトを生じるはずです。

+4

ポインタは符号なし序数スカラーであり、必ずしも整数ではありません。 – fortran

+1

一貫性/明快さのために、セグメンテーション違反がこのような状況での行動を考える過度に正確な方法ではないことに気づくことは価値がありません。任意のメモリアドレスを参照解除すると、Cでは未定義の動作になります。多くの場合、セグメンテーションフォールトが発生しますが、必須ではありません。それはバスエラーを引き起こすかもしれない(Mac OS Xはそれを好む)。そのアドレスが有効な場合は、そのアドレスの内容を表示することがあります。 –

+0

'C'は正しく初期化されていないポインタを検出するのが難しいですが、' int'データ型の参照解除を検出しません。それをコンパイルしている間、あなたを止める。しかし、あなたは '*(unsigned int *)a = 5'でそれを強制することができ、おそらくあなたが期待するセグメンテーションフォールトを得ることができます。低い確率では、「a」はプログラムコンテキスト内のアドレス指定可能な場所に変換される値を持つため、あなたはあなたの欠点を逃してしまいますが、ランダムなアドレス指定の微妙な欠陥を達成するため、「多分」と言います。 – nik

答えて

1

あなたが実際に「」の最初のケースを割り当てることはありません。

int* a = ? 
*a = 5; //BAD. What is 'a' exactly? 

int a = ? //but some int anyway 
*a = 5; //'a' is not a pointer! 

整数をポインタとして使用する場合は、最初にキャストする必要があります。ポインタは、の整数になることがありますが、概念的には異なる目的を果たします。

14

ポインタは、ない整数です。 C a)は、特定のプログラミングエラーを防止し、

b)は、彼らが実際には2つの整数(セグメントから成るので、いくつかのシステムでは

プログラムの可搬性を向上させる、ポインタは、整数ではないかもしれない

にデータ型を有しますオフセット)。他のシステムでは、intが32ビットでポインタが64ビットであるため、int型を使用してポインタを表現することはできません。これらの理由から、Cはintをポインタとして直接使用することを禁止しています。ポインタを保持するのに十分な大きさの整数型を使用する場合は、intptr_tを使用します。

-4

intが* - intへのポインタです。あなたがそれを初期化していない場所はどこにもありません。そのような質問をする前に、Cに関する本を読んでください。

+0

私は明白にそれがなぜ失敗するかを知っていると書いた... 私の質問はなぜ2番目のスニペットがコンパイルされないのだろうか? – dharm0us

+0

クラスのちょっとしたことが、あなたの答えに複数の下降声を避けることに長い道を行くでしょう。 –

3

あなたはポインタでない何か間接参照コンパイラを作ろうとしている

int a; 
*a = 5; 

あなたが言うとき。確かに、あなたはそれがポインタにを唱えられるし、それを間接参照し、そのように、

*((int*)a) = 5; 

を...、それはあなたが本当に、本当にそれをやりたいコンパイラに指示します。しかし、それは危険なことです。どうして?さて、あなたの例では、例えば、あなたが実際の値を初期化することはありませんので、あなたはポインタとしてそれを使用する場合、あなたは値が使用されて場所にすでにあるものは何でも持ってしようとしています。ローカル変数であるように見えるので、それは関数のスタックフレーム内の初期化されていない位置になり、何かになる可能性があります。本質的には、値5を未定義の場所に書き込むことになります。本当に賢明なことではありません!

2

それはポインタは単にアドレスを格納することを示しており、アドレスは多くの整数のように、数字として考えてよいことと言われています。しかし、通常、アドレスは構造体(ページ番号、ページ内オフセットなど)を持っています。

あなたは言葉でそれを取るべきではありません。整数には文字通り数字が格納されていますが、これを追加、減算することはできますが、ポインタとして使うことはできません。整数は整数で、ポインタはポインタです。彼らはさまざまな目的を果たします。

時には、整数へのポインタからのキャストが必要な場合があります(何らかの目的のために、OSカーネルでアドレス演算を行うことがあります)。その後、コンパイラが正しいサイズを保証して値を保持するかどうかを調べることで、ポインタをそのような整数型にキャストすることができます。しかし逆参照したい場合は、ポインタ型にキャストする必要があります。

0

演算子*は、整数データ型用に定義されていない単項演算子です。声明

*a = 5;

がコンパイルされません理由です。

また、整数とポインタは同じものではありません。これらは通常、メモリ内の同じサイズです(32ビットシステムでは4バイト)。