10秒目をつむったら…

#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 に関して
移植性のないポインタ変換と表記されますが
結果は同じだったのでポインタ定義というのは結局必要なんですか?
移植性のないポインタ変換とはなんなんですか?
よければ詳しく教えてください

A 回答 (4件)

p=&x;


だと整数にアドレスを代入しようとするのでワーニングになります。

int p; -- 整数そのもの
int *p; -- 整数がある場所

参考URLのポインタの説明を見ていただけると解ると思います。

参考URL:http://www.kumei.ne.jp/c_lang/intro/no_16.htm
    • good
    • 0

「移植性の無いポインタ変換」について詳しく知るには、コンピューターが


使用している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言語が開発されたか、と言う歴史について調べてみると、なぜコンパイラーが
「移植性」に付いてのウォーニングを出力するのか、話がわかってくるとおもいます。
    • good
    • 0

ポインタはメモリアドレスです。


メモリアドレスの構造は処理系依存であるため、「常に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;は大丈夫ですが、これも「常に安全」とは言い切れません。
    • good
    • 0

こんにちわ。



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

お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!


おすすめ情報