c - 执行 64 位负整数运算时出现意外结果

标签 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?

附言。我在 Visual Studio 2008 中运行这段代码。

最佳答案

让我们考虑一下这个声明

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

逐步执行。

首先有执行的子表达式

-10000000LL * (LONGLONG)uiDelaySec

它的类型是LONGLONG,它的值是

-50000000

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

ULONGLONG iiDaysOver = 0;

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

来自 C 标准

6.3.1.1 bool 值、字符和整数

— The rank of any unsigned integer type shall equal the rank of the corresponding signed integer type, if any.

6.3.1.8 常用的算术转换

Otherwise, both operands are converted to the unsigned integer type corresponding to the type of the operand with signed integer type.

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

-50000000

解释为非负值才会有值

18446744073659551616

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

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

或者是否将您的 typedef 用于基本类型

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

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

9223372036829775808?

可以表示为两种类型的非负值:LONGLONGULONGLONG。 所以这个值将被分配给 ii没有任何转换。

关于c - 执行 64 位负整数运算时出现意外结果,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/30366736/

相关文章:

编译实模式asm (rootkit.arsenal)

C:为什么数组的所有元素都相同

c# - 删除SQL Server中的存储过程

c++ - OpenGL:如何控制我的窗口将使用哪种缓冲方法?

visual-studio-2008 - 从单元测试生成经理报告 (Visual Studio)

c - execlp 行为异常

编译器相关 - 这两个 C 代码真的相同吗?

c - 我想用 C 创建一个简单的汇编程序。我应该从哪里开始?

asp.net - 如何以编程方式为 ASP.NET ReportViewer 控件设置数据源?

visual-studio - 编辑 aspx/母版页时 Visual Studio 2008 卡住