1

以下の同一の操作が2つの異なる出力を報告する理由を理解できませんでした。numが負の値であると宣言され、そのnumをbaseAddrに追加すると、addrが32ビットの範囲を超えていることがわかります。一方、numを正の値に宣言して減算を実行すると、正しい結果が得られます。つまり、結果の出力は正確に報告されます。誰かが以下の計算の何が問題になっているのか説明できますか?

/* Architecture is powerpc. Program cross-compiled for powerpc. Gcc Version- 4.6.2 */
#include <stdio.h>
typedef unsigned long long u_int64;
typedef unsigned long u_int32;

int main() {
   u_int64 baseAddr = 0x8e008128;
   u_int32 num = -360;
   u_int64 addr = baseAddr + num;
   printf("\nAddr 1st step = 0x%llx\n", addr);

   /* Same operation, but slightly different */
   num = 360;
   addr = baseAddr - num;
   printf("\nAddr 2nd step = 0x%llx\n", addr);
   return 0;
}

/* Output:
Addr printed is 0x18e007fc0, but I need just 0x8e007fc0
/diagsk10copy/bin # ./e500GPR

Addr 1st step = 0x18e007fc0 //Wrong
Addr 2nd step = 0x8e007fc0
*/
4

2 に答える 2

4

u_int32符号なしタイプです。-360を割り当てると、整数のオーバーフローが発生しnum、非常に大きな正の値が保持されます。

于 2012-09-26T20:17:54.640 に答える
3

u_int32署名されていません。割り当てた負の360数は、正の32ビット数として再解釈されます。これをに追加するとu_int64、値は32個のゼロで拡張され、他のオペランドのサイズと一致します。これはあなたが望んでいたことではありません:数が負だったので、加算の結果が最大値より1大きい数を法として減らされた後、加算が目的の効果を生み出すためには、上半分にすべてのものが必要です。u_int64*で表すことができます。

numをとして宣言するとu_int64、最初と2番目の部分が期待値を生成します(ideoneのデモ)。

u_int64 baseAddr = 0x8e008128;
u_int64 num = -360;
u_int64 addr = baseAddr + num; // Works!
printf("\nAddr 1st step = 0x%llx\n", addr);


* 6.2.5(9) "結果の符号なし整数型で表現できない結果は、結果で表現できる最大値より1大きい数を法として減少するため、符号なしオペランドを含む計算がオーバーフローすることはありません。タイプ。"。標準の関連部分を見つけてくれたDanielFischerに感謝します!

于 2012-09-26T20:30:11.503 に答える