1

SOでこの質問を読んでいました。最初の回答を読んだ後、 の理由を理解できませんでした-5 >> 1 = -3。その辺も少し工夫しました。

コードと出力もここで見ることができます。これが私がしたことです:

#include<stdio.h>

int main(){

printf("5/2 = %d\n",5/2);
printf("5 >> 1 = %d\n",5 >> 1);
printf("5/2 = %lf\n",5/2);
printf("5 >> 1 = %f\n",5 >> 1);
printf("-5/2 = %d\n",-5/2);
printf("-5 >> 1 = %d\n",-5 >> 1);
printf("-5/2 = %f\n",-5/2);
printf("-5 >> 1 = %f\n",-5 >> 1);

return 0;
}

出力:

5/2 = 2
5 >> 1 = 2
5/2 = 2.168831
5 >> 1 = 2.168831
-5/2 = -2
-5 >> 1 = -3
-5/2 = 2.168833
-5 >> 1 = 2.168833

理解できません5/2 == 2.168831, 5 >> 2 == 2.168831, 5 >> 1 == -3

なぜこれが起こっているのですか? (答えが非常に基本的である可能性があり、いくつかの基本的なことが欠けている可能性があるため、教えてください)。

4

2 に答える 2

9

の結果は で-5 / 2あり、またはではintありません。ただし、フォーマット指定子はであるため、意味をなさないとして解釈されるため、値が不安定になります。あなたがしていることは未定義の動作と呼ばれます: 何でも起こりえます.floatdouble%fintfloat

于 2013-01-13T10:32:18.330 に答える
3

実行した結果が表示される理由は次のとおりです。

引数を渡すときにintprintf 指定子を使用する場合double(この状況では a が afloatに変換されることに注意してくださいdouble)、ほとんどの C 実装は、引数を可変個引数関数 (多様な関数を受け入れる関数) にint渡すための通常の規則に従って引数を渡します。int引数の型)、しかし、ルーチンは、以下で説明するようにprintf、引数が渡されたかのようにマシンの状態を解釈します。double(これは常に起こるとは限りません。C 標準で定義された動作を離れると、C 実装は他のことを行う可能性があります。特に、驚くべき結果を引き起こすオプティマイザーとの複雑な相互作用が発生する可能性があります。しかし、これは起こることです。信頼することはできません。)

各コンピューティング プラットフォームには、引数の受け渡し方法に関するいくつかの規則があります。あるプラットフォームでは、すべての引数が右から左にスタックにプッシュされ、各引数が必要なバイト数だけを使用してスタックに置かれるように指定する場合があります。別のプラットフォームでは、引数を左から右にスタックにプッシュするか、次の 4 バイトの倍数まで引数をパディングして、スタックを適切に配置するように指定する場合があります。最近の多くのプラットフォームでは、特定のサイズ以下の整数引数は汎用レジスターで渡され、浮動小数点引数は浮動小数点レジスターで渡され、その他の引数はスタックで渡されるように指定されています。

が引数をprintf%fて探しているときに を渡した場合、何が見つかるでしょうか? このプラットフォームが両方の引数をスタックにプッシュすると、は のビットを見つけますが、それらのビットを . であるかのように解釈します。これにより、によって決定された値が表示されますが、とのエンコーディングではビットの意味がまったく異なるため、と明確な関係はありません。doubleintprintfprintfintdoubleprintfintintintdouble

このプラットフォームがint引数をある場所doubleに配置し、別の場所に引数を配置する場合、引数printfとはまったく関係のないビットがいくつか見つかりますintdoubleこれらは、たとえば、引数があるはずの浮動小数点レジスタにたまたま残ったビットです。それらのビットは、以前の作業の残りにすぎません。int取得する値は、渡したに対して基本的にランダムになります。渡された の 4 バイトと近くにある他の 4 バイトを取得することによりprintf、 a の 8 バイトを探して、ミックスを取得することもできます。doubleint

プログラムを複数回実行すると、同じ値が出力されることがよくあります。これには 2 つの理由があります。まず、コンピュータは機械的です。それらは主に決定論的な方法で動作するため、それらがあなたが使用している方法で使用されるように特に設計されていなくても、同じことを何度も繰り返します。第 2 に、オペレーティング システムが起動時にプログラムに渡す環境は、プログラムを起動するたびにほぼ同じです。そのメモリの大部分はクリアされるか、プログラム ファイルから初期化されます。メモリまたは他のプログラムの状態の一部が、コンピューターの他の環境から初期化されています。そのデータは、プログラムの実行ごとに異なる場合があります。たとえば、実行ごとに現在時刻が明らかに変化します。コマンド履歴も同様です。コマンド シェルが環境変数に設定したプラスの値。プログラムを複数回実行すると、結果が異なる場合があります。

仕様 (C 仕様、コンパイラ仕様、マシンおよびオペレーティング システムの仕様、またはその他のドキュメント) によって動作が定義されていないコードを使用する場合、そのコードの動作に依存することはできません。(C 標準で完全に指定されていなくても、その C コンパイラで指定されている特定の C コンパイラでコンパイルされたコードの動作に依存することができます。)

于 2013-01-13T12:17:01.433 に答える