9

このコードを実行しようとしましたが、

int *p;
float q;
q = 6.6;
p = &q;

警告になりますが、&qpは同じサイズだと思いますのでp、 のアドレスを持つことができますq。しかし、印刷する&qと、p異なる出力が得られます。これは私の出力です

*p =  6.600000 
 q = 0.000000, p = 0x40d33333, &q = 0x7fffe2fa3c8c 

私が見逃しているのは何ですか?andp&qは、ポインタと変数の型が同じ場合は同じです。

私の完全なコードは

#include<stdio.h>
void main()
{   
    int *p;
    float q;
    q = 6.6;
    p = &q;
    printf("*p =  %f \n q = %f, p = %p, &q = %p \n",*p,q,p,&q);
}
4

3 に答える 3

9

コンパイラの警告をもっと真剣に受け止める必要があります。

C では、コンパイラが無効なプログラムを拒否する必要はありません。ルール違反の「診断」が必要なだけです。診断は、致命的なエラー メッセージまたは警告のいずれかです。

残念ながら、互換性のないポインター型の割り当てに対してコンパイラが警告を発行するのはよくあることです。

void main()

これは間違っています; である必要がありますint main(void)。あなたのコンパイラはそれを回避できるかもしれませんし、目に見える問題を引き起こさないかもしれませんが、正しく書かないことには意味がありません。(それほど単純ではありませんが、これで十分です。)

int *p;
float q;
q = 6.6;

それで大丈夫です。

p = &q;

pタイプint*です。&qタイプfloat*です。(キャストなしで)一方を他方に割り当てることは、制約違反です。それを見る最も簡単な方法は、それが単に違法であるということです。

この割り当てを本当に実行したい場合は、キャストを使用できます。

p = (int*)&q; /* legal, but ugly */

しかし、そうする正当な理由はめったにありません。 pへのポインタintです。他の何かを指すようにする非常に正当な理由がない限り、intオブジェクトを指す必要があります。状況によっては、変換自体が未定義の動作をすることがあります。

printf("*p =  %f \n q = %f, p = %p, &q = %p \n",*p,q,p,&q);

%f形式にはdouble引数が必要です (引数はこのコンテキストでfloat昇格されるため、問題ありません)。しかし、タイプです。間違った型の引数で呼び出すと、プログラムの動作が未定義になります。doublefloat*pintprintf

%pvoid*ポインタ型だけでなく、 type の引数が必要です。ポインター値を出力したい場合は、次のようにキャストする必要がありますvoid*

printf("&q = %p\n", (void*)&q);

キャストなしで動作する可能性がありますが、動作は未定義です。

プログラムをコンパイルするときに警告が表示された場合は、わざわざ実行する必要はありません。最初に警告を修正します。

あなたのタイトルの質問に関しては、タイプのポインターint*float*は異なるタイプです。はオブジェクトint*を指す必要があります。intaはオブジェクトfloat*を指す必要がありfloatます。コンパイラはそれらを混在させることができますが、その結果は実装定義または未定義のいずれかになります。C 言語、特に多くの C コンパイラでは、あまり意味のない多くのことを回避できます。

それらが異なるタイプである理由は、それらの使用におけるエラーを防止する、または少なくとも検出するためです。type のオブジェクトを宣言する場合は、それがオブジェクトint*を指すことを意図していると言っていintます (null ポインターでない場合)。オブジェクトのアドレスをfloatオブジェクトに保存するint*ことは、ほぼ間違いなく間違いです。型安全性を強制することで、そのような間違いをできるだけ早く (重要なクライアントのデモ中にプログラムがクラッシュしたときではなく、コンパイラが警告を出力したときに) 検出できます。

int*float*が同じサイズで、同じ内部表現を持っている可能性があります (ただし、保証はされません) 。しかし、オブジェクトの意味は、int*「仮想アドレスを含む 32 (または 64) ビットの集まり」ではなく、「intオブジェクトを指すもの」です。

于 2013-04-03T15:22:21.843 に答える
0

teppicさんの言うことに加えて、

検討、

int a = 5;
int *p = &a;

この場合p、整数を指すことをコンパイラに示します。そのため、実行時に のようなことを行うと*p、no. のサイズに等しいバイト数intが読み取られます。

xよりもバイト数の少ないデータ型のアドレスを保持するように宣言されているポインターに、バイト数を占めるデータ型のアドレスを割り当てるとx、間接演算子を使用したときに間違ったバイト数が読み取られます。

于 2013-04-03T15:20:48.680 に答える