执行64位负整数运算的意外结果

时间:2015-05-21 07:03:54

标签: c visual-studio-2008

说明我的问题的最好方法是通过我的实际代码中的这个代码段:

ULONG uiDelaySec = 5;

ULONGLONG iiDaysOver = 0;
LONGLONG ii = -10000000LL * (LONGLONG)uiDelaySec / (2 + iiDaysOver);

//Why do I get 'ii' equal to 9223372036829775808?

PS。我在Visual Studio 2008中运行此代码。

3 个答案:

答案 0 :(得分:3)

让我们考虑一下这句话

LONGLONG ii = -10000000LL * (LONGLONG)uiDelaySec / (2 + iiDaysOver);

是一步一步执行的。

首先执行子表达式

-10000000LL * (LONGLONG)uiDelaySec

它的类型为LONGLONG,其值为

-50000000

然后,此结果必须除以(2 + iiDaysOver)类型的操作数ULONGLONG,因为iiDaysOver定义为

ULONGLONG iiDaysOver = 0;

要执行操作,编译器应使用公共类型作为其操作数。左操作数的类型为LONGLONG,而右操作数的类型为ULONGLONG。根据通常算术转换的规则,如果两种类型具有相同的等级,则签名类型将转换为无符号类型。

来自C标准

6.3.1.1布尔,字符和整数

  

- 任何无符号整数类型的等级应等于   相应的有符号整数类型,如果有的话。

6.3.1.8通常的算术转换

  

否则,两个操作数都将转换为无符号整数类型   对应于带有符号整数类型的操作数的类型。

因此左操作数将转换为类型ULONGLONG。你会得到左操作数的负值

-50000000

被解释为非负值将具有值

18446744073659551616

为了确保它确实有效,您可以插入语句

printf( "%llu\n", ( unsigned long long )-50000000LL );

或者如果要将typedef用于基本类型

printf( "%llu\n", ( ULONGLONG )-50000000LL );

将此值除以2将得到无符号值

9223372036829775808?

可以在两种类型中表示为非负值:LONGLONGULONGLONG.因此,此值将在没有任何转化的情况下分配给ii

答案 1 :(得分:0)

VS中的调试器窗格被窃听。如果你sprintf你的变量是正确的ISelectionProvider provider = ... a selection provider such as a TreeViewer or TableViewer Control control = control to own the menu - usually the TreeViewer or TableViewer control MenuManager menuMgr = new MenuManager("#PopUp"); menuMgr.setRemoveAllWhenShown(true); menuMgr.addMenuListener(new IMenuListener() { @Override public void menuAboutToShow(IMenuManager manager) { // Additions placeholder manager.add(new Separator(IWorkbenchActionConstants.MB_ADDITIONS)); // Note: you can add other menu items directly here } }); Menu menu = menuMgr.createContextMenu(control); control.setMenu(menu); // register the context menu such that other plug-ins may contribute to it getSite().registerContextMenu(menuMgr, provider);

非常奇怪的是,如果我更改了下面的代码,则调试窗格是正确的。

-25000000

关键是如果是最后一个除法:如果用uint64_t执行,调试视图会被窃听,而uint32_t不是......

答案 2 :(得分:0)

问题似乎在于-10000000LL * (long long)uiDelaySec(2 + iiDaysOver),因为后者是无符号长long int,前者是无符号值。我的C-Fu不足以解释为什么会发生这种情况,但是下面的行给出了预期的结果,至少使用gcc:

long long int ii = -10000000LL * (long long)uiDelaySec / (long long int)(2 + iiDaysOver);