【问题标题】:Casting twice in the same line在同一行中投射两次
【发布时间】:2013-06-18 15:54:58
【问题描述】:

我在项目中看到了这段代码。

b的类型是void*

void *b = ...;
int a = (int) (unsigned long) b;

这条线没有意义吗?我的意思是,在所有情况下都与a = (int) b 相同?

【问题讨论】:

    标签: c casting


    【解决方案1】:

    这可能避免在 64 位 Unix 系统上出现编译器警告,其中 unsigned long 是 64 位数量,因此大到足以容纳指针,但 int 是 32 位数量,不足以容纳拿着指针。转换为(unsigned long) 保留地址的所有位;随后转换为int 会丢弃地址的高位 32 位,但默认情况下不会收到警告。

    演示:

    int main(void)
    {
        void *b = (void *)0x12345678;
        int   a = (int)(unsigned long)b;
        int   c = (int)b;
        return a + c;
    }
    
    $ gcc -O3 -g -std=c99 -Wall -Wextra -c ar.c
    ar.c: In function ‘main’:
    ar.c:5:15: warning: cast from pointer to integer of different size [-Wpointer-to-int-cast]
    $
    

    在 Mac OS X 10.8.4 上使用 GCC 4.7.1,默认为 64 位编译。

    推测“地址的一部分”值会做什么是很有趣的。

    【讨论】:

    • 请注意,有创造力的人会将数字(或布尔值)信息隐藏在 void*s 中 :)
    • 这是否让我有创意——使用我在您评论时编写的示例代码?
    • 呵呵,确实如此,因此 +1 :) 严肃地说,很多 API 使用 void*,而 intptr_t 本来是合适的
    • 而且很多 API 都使用void *,使用该 API 的程序员最好使用不透明的结构类型:extern struct opaque *xyz_create(int); extern void xyz_free(struct opaque *);。如果将struct opaque 替换为void *,则可以将任何旧指针传递给xyz_free() 函数,但使用struct opaque,则不能将任何旧指针传递给它。
    • +1 表示创意 :) 也许应该提到原始代码中的另一个问题,即从无符号类型到有符号类型的转换是实现定义的。此外,在您的示例代码中,您不需要对int 进行两次强制转换。
    【解决方案2】:

    在 x64 位环境下,直接类型转换为指向较小类型 say int 的指针可能会导致某些编译器(如 Clang)出现编译错误。

    例如:

     void *p = GetSomeAddress;
     int i = (int)p;  //error on compilers like Clang.
    

    解决办法是:

    int i = (int)(unsigned long)p;
    

    int i = (int)(long)p;
    

    这是因为,在 Unix 上,在 LP64 模型下,long 是 64 位的。

    在这种情况下,您需要彻底了解为什么需要将指针类型转换为 int 或其他可能导致数据丢失的较小类型。

    这个问题也可能对您有所帮助。 How should I handle "cast from ‘void*’ to ‘int’ loses precision" when compiling 32-bit code on 64-bit machine?

    【讨论】:

      【解决方案3】:

      我在我的项目中也看到了这一点。

      就我而言,“b”的内容由用于进程间通信的其他源/中间件填充。

      一旦填充了“b”,程序将通过强制转换获取“b”的内容到正确的字段“a”。然后应用程序使用“a”进行处理。

      我的项目使用 char* 而不是 void*。

      【讨论】:

        猜你喜欢
        • 2021-05-28
        • 2017-06-19
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2012-03-15
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多