-1

私はそのようなコードを持っています:

double x = 100.1;
double y;
int *p;

p = (int *) &x;
y = *p;

cout << "y value is: " << y << endl;

私はそれが間違っていることを理解しており、8 バイトではなく 4 バイトを取得しています。また、浮動小数点数にはメモリ上でトリッキーな表現があることも知っていますが (方法はわかりません)、このスクリプトでは次のような出力が得られます。

y value is: 1.71799e+09

私が理解しているように、それは浮動小数点でも価値があります。私のポインタはintであり、intの結果も期待しています。なぜそうではないのですか?理解するために何を読むべきですか?

4

7 に答える 7

6

私のポインタはintであり、intの結果も期待しています。なぜそうではないのですか?

yint ではなく double であるためです。ここで、整数値を持たない理由を尋ねるつもりならy、int (整数値を持つ必要があります) を double に変換した結果であるはずなので、次の出力を見てください。

std::cout << "y value is: " << std::fixed << y << '\n';

表示される出力は次のとおりです。

y value is: 1717986918.000000

したがって、整数値をy 持っているので、科学表記法を使用して単純に出力しました。がなぜyこの特定の整数値を持っているのか不思議に思うなら、それはそれ*pが持っていた値だからです。

std::cout << "*p is: " << *p << '\n';

*p is: 1717986918

xの値を持つ のメモリ ダンプを見ると、次のように表示され100.1ます。

66 66 66 66 66 06 59 40

これを int としてアクセスすると66 66 66 66、10 進数に変換すると 1717986918 になります。


もう 1 つ注意すべき点は、これは C++ では保証されていないということです。x実際、 int へのポインターを介してdouble にアクセスすると、エイリアシング規則に違反しているため、プログラムは実際には合法ではありません。あなたのプログラムは合法的に作られ、同じ結果を得ることができますが、C++ は浮動小数点値の表現を指定していないため、特定の整数値は合法的に異なる可能性があります。


理解するために何を読むべきですか?

これはフロートの表現で遊ぶ記事です: http://ridiculousfish.com/blog/posts/float.html

C++ は float の表現方法を指定していませんが、ほとんどの C++ 実装は IEEE-754 を使用しているため、その仕様も参照してください。これを始めるためのウィキペディアのページは次のとおりです: https://en.wikipedia.org/wiki/IEEE_floating_point

C++ のエイリアシング規則について学ぶには、仕様を見つけて読むことができます。厳密なエイリアシングは、§3.10/10、IIRC でカバ​​ーされています。SO では、エイリアシングに関する多くの質問と回答もあります。

于 2013-06-01T16:24:54.633 に答える
4

1.71799e+09整数 1,717,99x,xxx の浮動小数点表現です。

于 2013-06-01T15:31:00.627 に答える
4

私のポインタはintであり、intの結果も期待しています。なぜそうではないのですか?

あなたのポインター int *で、結果取得しています。int

しかし、それはあなたが表示しているものではありません。表示yしているのはdouble.

1.71799e+09あなたが得たの二重表現intです。

于 2013-06-01T15:33:39.127 に答える
3

あなたがするとき

y = *p;

変数yは、pが指すintを受け取り、それを double に変換します。

sizeof(double)8 でsizeof(int)が 4であるとします。

値 100 をxの 8 バイトにx = 100;入れますか。次に、8 バイトのうち 4 バイトのみをint値として使用し、その数値をdoubleに変換します。doubley = *p;

doubleintのバイナリ形式は異なります。たとえば、doubleとしての 100 は、100 intと同じ方法で表されません(8 対 4 などのサイズの違いは言うまでもありません)。

このリンクを参照してください

于 2013-06-01T15:30:22.827 に答える
3
double x = 100.1;
double y;
int *p;

p = (int *) &x;      
// Set a pointer of type integer to point at a floating point. Better C++ style
// would be p = reinterpret_cast<int *>(&x);
// which explains more clearly what you are doing - reinterpreting the pointer as
// a different type. 

y = *p;
// *p is an integer. So y is set to the value of *p, which is some crazy 
// integer value formed from the interpretation of a double as integer.

cout << "y value is: " << y << endl;

上記のコードのコメントを参照してください。別のタイプのデータを指すポインターを作成しているのに、変換された 2 進数が元の表現を表していないのはなぜなのか疑問に思っています...

(技術的には、このコードはエイリアシングに関する規則に違反しています。基本的に、2 つの異なる目的で同じメモリを使用しています。この場合、コンパイラは「正しいことを行う」義務はありません。この特定のケースで期待できることの一部 - double の最初の 4 バイトで表される整数値を取得することが期待される場合、つまり)。

y実際に数値の整数表現を に含めたい場合は、次のようにしxます。

y = (int)x; 

ポインターを使用してこの変換を行う賢明な方法はありません。

于 2013-06-01T15:34:18.963 に答える
0

次の行を実行すると、未定義の動作がトリガーされます。

p = (int *) &x;

未定義の動作をトリガーすると、未定義の動作についての推論が意味をなさないため、質問の残りの部分はかなり無意味です(ただし、質問の残りの部分を見ても、この未定義の動作のビットはあなたが何に影響しない可能性があります'本当に尋ねています。よくわかりませんが.)

于 2013-06-01T15:40:33.490 に答える
-1

C++ ポインターとデータ型のドキュメントを読む

http://www.cplusplus.com/doc/tutorial/pointers/

http://www.cplusplus.com/doc/tutorial/variables/

于 2013-06-01T15:39:37.630 に答える