26

Visual C++ 2012 を使用しており、コマンド ラインから次のファイルをコンパイルしています。

#include <stdio.h>
int main()
{
    printf("%.5f", 18/4+18%4);
    return 0;
} 

ランタイム エラー R6002 を回避するために、LIBCMT ではなく MSVCRT.LIB とリンクします。
出力される値は、このプログラムでは 0.00000 です。

ただし、C ++でまったく同じことを実行すると

 #include <iostream>
 using namespace std;
 int main()
 {
      cout << 18/4+18%4 << endl;
      return 0;
 }

これで、本来のように 6 が出力されます。

違いは何ですか?言語自体 (C と C++) または出力方法 (cout と printf) に関係しているのでしょうか、それとも MSVC の単なる癖ですか?

4

9 に答える 9

64

18/4+18%4は に評価されint、float を要求しています。常に警告を有効にしてコンパイルし、それらに注意を払う必要があります (警告は発生するのを待っているバグであると彼らは言いますが、彼らは正しいです)。

これは私のコンパイラ(GCC 4.8.1)が教えてくれることです(そして強制しなくても-Wall):

warning: format ‘%.5f’ expects type ‘double’, but argument 2 has type ‘int’

一方、std::cout<<操作は式のタイプを推測し、それを画面に正しくストリーミングできます。

于 2013-09-30T20:06:04.500 に答える
37

C 関数に整数が渡されていますが、( を使用して%f) 倍精度浮動小数点数を期待するように指示しているため、関数は失敗します。C++ 関数は、整数が渡されていることを認識しているため、適切に機能します。

于 2013-09-30T20:05:44.823 に答える
11

表現

18 / 4 + 18 % 4

intに評価されます。

しかし、printfフォーマット文字列"%.5f"は double を想定しています。

c++ と ostreams を使用すると、言語は出力の型を自動的に決定できます。

Cコードを次のように変更するだけです:

#include <stdio.h>
int main()
{
    printf("%d", 18 / 4 + 18 % 4);
    return 0;
}
于 2013-09-30T20:08:33.157 に答える
8

他の人は、printf() ステートメントで int/double の不一致を正しく指摘しています。「実行時エラー R6002 を回避するために、LIBCMT ではなく MSVCRT.LIB とリンクする」というあなたの声明についてコメントしたいと思います。このような単純なプログラムは、ランタイム環境に過度に負担をかけるべきではないため、このようなランタイム エラーは、コード内で未定義の動作を示す危険信号である必要があります。

「MSVCRT R6002」の簡単なGoogleは次のように述べています。

C 実行時エラー R6002 浮動小数点サポートが読み込まれていません

必要な浮動小数点ライブラリがリンクされていません。次の考えられる原因を確認して修正するには

  1. プログラムは、/FPi87 などのコプロセッサを必要とするオプションを使用してコンパイルまたはリンクされましたが、コプロセッサがインストールされていないマシンでプログラムが実行されました。
  2. printf_s または scanf_s 関数のフォーマット文字列に浮動小数点フォーマット仕様が含まれていましたが、プログラムには浮動小数点値または変数が含まれていませんでした。
  3. コンパイラは、必要な場合にのみ浮動小数点サポートをロードすることで、プログラムのサイズを最小限に抑えます。コンパイラは、フォーマット文字列内の浮動小数点フォーマット指定を検出できないため、必要な浮動小数点ルーチンをロードしません。
  4. 浮動小数点引数を使用して浮動小数点フォーマット仕様に対応させるか、プログラム内の別の場所で浮動小数点代入を実行してください。これにより、浮動小数点サポートが読み込まれます。
  5. 混合言語プログラムで、プログラムがリンクされたときに C ライブラリーが FORTRAN ライブラリーの前に指定されました。最後に C ライブラリを再リンクして指定します。

もちろん、ここでの教訓は、コンパイラとランタイムの警告とエラーに細心の注意を払う必要があるということです。疑わしい場合は、コンパイラではなく、コードに問題があると常に想定してください。

于 2013-10-01T11:03:24.347 に答える
4

C では、printf 書式指定子で浮動小数点 ("%f") を明示的に指定しているため、浮動小数点引数が必要です。しかし、「int」引数を指定しているため、問題が発生します。

何をしようとしているかに応じて、次のことができます。

1)(そうでなければ整数)式をfloatにキャストする

および/または

2) C で "%.5f" を使用するのと同じように、cout ストリームでsetprecisionを使用します。

#include <iostream>
using namespace std;
int main()
{
   float x = 18/4+18%4;
   std::cout << std::setprecision(5) << x << endl;
   return 0;
}

3)整数が必要な場合は、使用しますprintf ("%d", 18/4+18%4);

于 2013-09-30T20:05:38.673 に答える
1

数値の 1 つを浮動小数点値にします。

#include <stdio.h>
int main()
{

    printf("%.0f", 18/4.0+18%4);
    return 0;
} 
于 2013-09-30T20:16:40.307 に答える
0

考えられる代替手段の 1 つは、リテラル (または式自体) を型キャストすることです。

#include <stdio.h>

int main(void)
{
    printf("%.5f", (float)18/4+18%4);
    return 0;
}
于 2013-10-01T10:34:48.060 に答える