質問
(AIX 5.3に)のxlC 8.0でコンパイルこのコードは、間違った結果を生成します。
それは12345
を印刷、代わりに804399880
を印刷しなければなりません。
const
の前でresult
を削除すると、正しくコード作業を行います。
どこにバグがありますか?
#include <stdio.h>
#include <stdlib.h>
#include <string>
long int foo(std::string input)
{
return strtol(input.c_str(), NULL, 0);
}
void bar()
{
const long int result = foo("12345");
printf("%u\n", result);
}
int
main()
{
bar();
return 0;
}
コンパイルコマンド:
/usr/vacpp/bin/xlC example.cpp -g
編集:「%ldの\ nは」に上記のprintf書式文字列を変更することは助けにはなりません。 編集2:使用AIXのバージョンは5.3、6.1ないし
。解決
のxlC 10.0作品の罰金は、
コンパイラのバグのようです他のヒント
これは++タグ付きCですので、何をcoutを使用するときに起こることの代わりにprintfの?
の 問題は、あなたがunsigned int型を印刷している占いのprintfで、その後、それを実際に印刷するための符号付きlong int型を送信するようにに見えます。最も可能性の高いメモリレイアウトが異なっており、printfのは、あなたが実際にやってみたかったのかを理解することはできません。
これはなぜconstの事項推測のビットになるだろう、しかし、1つは、合理的な仮定をすることができます。
このようなresult
としてブロックスコープを持つ変数は、レジスタに割り当てられた、またはスタックに置くことができます。レジスタが使用されているかどうかに影響を与える多くの要因があります。これは、この場合には、そのconst
の問題は非常に可能です。最後に、それはそれは最高の作品と考えて何を右使用するコンパイラです。
は同様に、関数の引数は、レジスタまたはスタックに渡すことができます。機能は、多くの場合、別々の引数が進み、それらのインタフェース(即ち宣言)おもむくにコンパイルされます。それは、異なる種類の引数で呼び出すことができますようのprintf(...)は、特殊なケースです。その結果、どのようなデータが異なりますどこまで終了し、あなたが期待するものを(...)printf関数を指示する必要があります。
関数に変数を渡すとき次に、コンパイラは通常、それをコピーする必要があります。レジスタからスタック、1レジスタに他に、エトセトラ、可能なかなりの数のバリエーションがあります。私が示されているように、ソース位置はconst
の有無に応じて異なる場合があります。
printf(...)
に誤った書式指定子を渡す起こるようにさて、すなわち%u
の代わりに%ld
。おそらく代わりに、スタック、または他の方法で回避のレジスタに - これはprintfの(...)がそのデータを取得するために間違った場所に見えることがあります。このような行動は非常に驚くべき結果を引き起こす可能性があります。 printf(...)
は、インスタンスあなたの未コピーresult
全体でつまずき、またはいくつかのレジスタのランダム古い値のためでした。これは、非constの場合には、constのケースprintf(...)
にちょうどゴミを見つけたのに対し、(それは間違った場所にそれを発見した可能性があるにもかかわらず)正しい値を見つけるために起こると思われます。
おそらく関連しますが、注意が必要ではない:uはprintf関数指定子%は、符号なし整数を示していますが、符号付き整数を渡している。
。G ++はこれだけで罰金を処理し、警告を言及していません。これは、printfの文句ありません。あなたはlong int型のため%のLUを使用する必要があります。またはより良い、%LDを使用するか(符号なしlong int型)にキャストします。