• ベストアンサー

ポインタ定義は必要なんですか?

#include <stdio.h> int main( void ) { int x; int *p; p = &x; printf("Address = %p\t\n", p ); return 0; } を #include <stdio.h> int main( void ) { int x; int p;←ここを上とはかえた p = &x; printf("Address = %p\t\n", p ); return 0; } にしたところコンパイル時に p = &x に関して 移植性のないポインタ変換と表記されますが 結果は同じだったのでポインタ定義というのは結局必要なんですか? 移植性のないポインタ変換とはなんなんですか? よければ詳しく教えてください

質問者が選んだベストアンサー

  • ベストアンサー
回答No.3

p=&x; だと整数にアドレスを代入しようとするのでワーニングになります。 int p; -- 整数そのもの int *p; -- 整数がある場所 参考URLのポインタの説明を見ていただけると解ると思います。

参考URL:
http://www.kumei.ne.jp/c_lang/intro/no_16.htm
すると、全ての回答が全文表示されます。

その他の回答 (3)

noname#40977
noname#40977
回答No.4

「移植性の無いポインタ変換」について詳しく知るには、コンピューターが 使用しているCPUの仕組みについて知る必要があります。 CPUには「レジスタ」と呼ばれるデータを保存するメモリの一種を持っています。 通常、CPUは複数のレジスタを備えています。 ほとんどのCPUは、このレジスタに格納されたデータに対して演算を行います。 (メインメモリに置かれたデータを直接演算できるCPUも数多く 有りますが、レジスタに格納されたデータ演算の方が高速なため、 通常はメインメモリからレジスタにデータをコピーしてから演算を行います。) このレジスタには使用目的別に数種類あり、大きく分けてメインメモリにアクセスするときのアドレスを格納するものと、数値演算を行うためのものの2つに分けられます。 (CPUの種類によってはこの区別が無いものも有ります。) この「メインメモリにアクセスする時のアドレス」を格納するのがC言語での ポインタ変数、そして「数値演算を行うためのデータ」がC言語でのintやfloatなどの変数に相当します。 ここで「移植性の無い」理由の説明に戻りますが、 多くのCPUではアドレスを格納するレジスターのビット数とデータを格納するレジスターのビット数が違っています。 たとえば、Pentium4の場合はアドレス・データ(MMX/SSE用を除き)共に 32ビットのレジスタ-を使用していますが、Pentium4のルーツである8ビット CPU、8080の場合はアドレス用レジスターが16ビット、データ用レジスターが 8ビットになっていました。また、旧型のMacintoshで使用されていた68000の場合はデータが16ビット、アドレスが32ビットでした。 (Intel Pentium4を含む8086系列のCPUの場合、アドレスレジスタの ビット数については話が複雑なので上記の説明は正確ではありませんが ここでは簡略化して説明しています。) そして、C言語のintは、通常、データ用レジスターのビット数と一致し、 ポインタ変数はアドレス用レジスターのビット数と一致します。 アドレスとデータの両レジスターのデータ幅(ビット数)が同じならば、 計算対象のデータもそれを格納するアドレスもいっしょなので、 C言語のポインタ変数の持つ値もint型変数が持つ値も最終的には 同じビット数のデータとみなされるため代入が可能なのですが、 上記の例の8080の様に両レジスターのビット数が違う場合には この代入は不可能(もしくはデータの一部しか代入されない状態)になります。 これが「移植性のないポインタ変換」の理由です。 つまり、ここでいう「移植性」とは、コンピューターの使っているCPUが 違っていても同じプログラムが実行できるかどうか、と言うことを示しているわけです。 なぜC言語が開発されたか、と言う歴史について調べてみると、なぜコンパイラーが 「移植性」に付いてのウォーニングを出力するのか、話がわかってくるとおもいます。

すると、全ての回答が全文表示されます。
  • toysmith
  • ベストアンサー率37% (570/1525)
回答No.2

ポインタはメモリアドレスです。 メモリアドレスの構造は処理系依存であるため、「常にint型の変数に代入可能」とは限りません。 例えば、MacOS6以前のMacintoshではintが16bitの処理系が主流でした。 (当時のMacintoshの母国語がPascalであり、PascalのIntegerが16bitであるため) しかし、当時のMacintoshが搭載していたCPUであるMC68000シリーズは32bitアドレスを持っていいたため、int p = &x;では安全な代入が期待できません。 MS-DOS時代に使われていたCPU8086ではもっと複雑で、アドレスサイズが16bitの場合と32bitの場合があり、intは16bitでした。 この場合もポインタからintへの代入は安全ではありません。 このような処理系ではunsigned long p = &x;は大丈夫ですが、これも「常に安全」とは言い切れません。

すると、全ての回答が全文表示されます。
  • muyoshid
  • ベストアンサー率72% (230/318)
回答No.1

こんにちわ。 int x; int p; p = &x; としてもコンパイルは通りますが、その後ポインタの演算を行うと 結果が異なってきます。 (p++ 等) データの幅と言う事ではint とポインタは同じですが 演算結果はint とポインタは全く別のものです。

すると、全ての回答が全文表示されます。

関連するQ&A