UINT One = 1;
LONG mylong = LONG(-1) * One;
LONGLONG mylonglong1 = LONG(-1) * One;
LONGLONG mylonglong2 = LONG(LONG(-1) * One);
mylong
,mylonglong1
和mylonglong2
中存储的值是多少?
mylong = 0xffffffff (ok)
mylonglong1 = 0x00000000ffffffff (why?)
mylonglong2 = 0xffffffffffffffff (ok)
我很惊讶地知道mylonglong1
的结果,更惊讶的是没有编译警告。
为什么将LONG分配给LONGLONG会导致左边的填充为零?
项目中发生的事情是使用函数CFile :: Seek()
时遇到的问题virtual LONG Seek( LONG lOff, UINT nFrom );
此处定义:https://msdn.microsoft.com/en-us/library/aa270542(v=vs.60).aspx 迁移到
virtual ULONGLONG Seek( LONGLONG lOff, UINT nFrom);
此处定义https://msdn.microsoft.com/library/b2eb5757-d499-4e67-b044-dd7d1abaa0f8.aspx#cfile__seek
迁移后,它不再起作用,因为lOff
的参数转换没有给出预期的结果。
答案 0 :(得分:2)
在表达式(-1) * (UINT)1
中,第一个操作数根据operand conversion rules转换为UINT
:
否则,如果无符号操作数的转换等级大于或等于带符号操作数的转换等级,则带符号操作数将转换为无符号操作数的类型。
因此,我们有一个无符号乘法,结果类型为UINT
。从UINT
到LONGLONG
的转换非常简单,因为LONGLONG
可以代表UINT
所代表的每个数字,在本例中为0xffffffff
。这就是你最终得到0x00000000ffffffff
的方式。
现在,当您执行LONG(LONG(-1) * (UINT)1)
时,上述规则仍适用,但您最终会将未签名的0xffffffff
转换为-1
,然后将其符号扩展为LONGLONG
P.S:我假设Win32 / Win64,其中UINT和LONG是32位,LONGLONG是64位。