微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

转换为uint64时,int32或32位指针的意外符号扩展

我使用Visual Studio 2010(cl.exe / W4)将此代码编译为C文件
int main( int argc,char *argv[] )
{
    unsigned __int64 a = 0x00000000FFFFFFFF;
    void *orig = (void *)0xFFFFFFFF;
    unsigned __int64 b = (unsigned __int64)orig;
    if( a != b )
        printf( " problem\ta: %016I64X\tb: %016I64X\n",a,b );
    return;
}

没有警告,结果是:

problem a: 00000000FFFFFFFF b: FFFFFFFFFFFFFFFF

我想int orig =(int)0xFFFFFFFF会引起争议,因为我没有指定一个整数的指针.但结果是一样的.

有人可以向我解释在C标准中它覆盖了orig是从0xFFFFFFFF扩展到0xFFFFFFFFFFFFFFFF的符号吗?

我原以为(unsigned __int64)orig会变成0x00000000FFFFFFFF.似乎转换首先是签名的__int64类型,然后它变为无符号?

编辑:这个问题已被回答,指针是符号扩展,这就是为什么我在gcc和msvc中看到这种行为.但是我不明白为什么当我执行类似(unsigned __int64)(int)0xF0000000时它的符号扩展到0xFFFFFFFFF0000000但是(unsigned __int64)0xF0000000并没有反而显示我想要的是0x00000000F0000000.

编辑:上述编辑的答案. (unsigned __int64)(int)0xF0000000符号扩展的原因是因为,如用户R所述:

Conversion of a signed type (or any type) to an unsigned type
always takes place via reduction modulo one plus the max value of
the destination type.

并且在(无符号__int64)0xF0000000 0xF0000000作为无符号整数类型开始,因为它不能适合整数类型.接下来,已经无符号的类型转换为unsigned __int64.

因此,对我来说这是一个函数,它返回一个32位或64位指针作为无符号__int64进行比较我必须首先将32位应用程序中的32位指针转换为无符号类型,然后再将其提升为unsigned __int64.结果代码看起来像这样(但是,你知道,更好):

unsigned __int64 functionidontcontrol( char * );
unsigned __int64 x;
void *y = thisisa32bitaddress;
x = functionidontcontrol(str);
if( x != (uintptr_t)y )

再次编辑:
这是我在C99标准中找到的:
6.3.1.3有符号和无符号整数

> 1当具有整数类型的值转换为另一个整数时
如果值可以由new表示,则为_Bool以外的类型
类型,它没有变化.
> 2否则,如果新类型是无符号的,则转换为
重复加或减一个以上的最大值
可以在新类型中表示,直到值在
新型的范围.49)
> 3否则,新类型已签名且值不可
代表其中;结果是实现定义的还是
提出了实现定义的信号.
> 49)规则描述了数学值的算术,而不是
给定类型表达式的值.

将指针转换为/从整数转换是实现定义的.

Here是gcc如何做到的,即如果整数类型大于指针类型,则符号会扩展(无论整数是有符号还是无符号,都会发生这种情况,因为这就是gcc决定实现它的方式).

据推测,msvc表现相似.编辑,我在MSDN上找到的最接近的东西是this/this,这表明将32位指针转换为64位也符号扩展.

原文地址:https://www.jb51.cc/windows/371679.html

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。

相关推荐