转换" void *"到没有警告的

时间:2016-09-04 17:54:37

标签: c++

我需要转换" void *"到int,但编译器一直给我警告。 不知道是否有办法改变代码,以便编译器不会抱怨。这在代码库中发生了很多,特别是在传递参数以启动新线程时。

$ g++ -fpermissive te1.cc
te1.cc: In function ‘void dummy(void*)’:
te1.cc:4:15: warning: cast from ‘void*’ to ‘int’ loses precision [-fpermissive]
  int x = (int)p;
               ^

这是简单的代码" te1.cc":

#include <stdio.h>

extern void someFunc(int);
void dummy(int type, void *p) {
    if (type == 0) {
        int x = (int)p;
        someFunc(x);
    } else if (type == 1) {
        printf("%s\n", (char*)p);
    }
}

int main(int argc, char *argv[]) {
    void *p = (void*)5;
    dummy(p);
    return 0;
}

UDPATE1

我明白我会失去精确度。它有时是有意的。我需要的是有一种方法可以在我知道的地方删除警告,确保它是安全的。很抱歉没有在之前说清楚。

UDPATE2

更新了代码段,以便说明重点。该参数需要传递不同类型的值。我需要一种方法来施放而不产生警告。

2 个答案:

答案 0 :(得分:7)

  

我需要将“void *”转换为int

不,你没有。

  

我真的...

不,你需要将指针表示为某种整数类型,保证不会丢失信息。

#include <cstdio>
#include <cstdint>
#include <iostream>
#include <cstring>
#include <utility>
#include <cinttypes>

void dummy(void *p) {
    std::intptr_t x = reinterpret_cast<std::intptr_t>(p);
    printf("x = %" PRIiPTR "\n", x);
// ^^ see here: http://en.cppreference.com/w/cpp/types/integer
}

int main(int argc, char *argv[]) {
    void *p = (void*)5;
    dummy(p);
    return 0;
}
  

好吧,我真正想做的是以符合标准的方式使用32位值。

这是std::uint32_t的用途:

#include <cstdint>
#include <iostream>

void dummy(std::uint32_t x) {
  std::cout << x << '\n';
}

int main(int argc, char *argv[]) {
    auto x = std::uint32_t(5);
    dummy(x);
    return 0;
}

std::uint32_t - 保证是无符号32位

std::int32_t - 保证签名为32位

答案 1 :(得分:5)

您可能正在寻找符合

的内容
int x = static_cast<int>(reinterpret_cast<std::uintptr_t>(p));

这并不能严格保证工作:也许令人惊讶的是,标准保证指针转换为足够大的整数并返回指针会产生相同的值;但是,当整数转换为指针并返回整数时,并没有提供类似的保证。所有关于后一种情况的说法都是

  

[expr.reinterpret.cast] / 4 指针可以显式转换为足以容纳它的任何整数类型。映射函数是实现定义的。 [注意:对于那些了解底层机器的寻址结构的人来说,这并不奇怪。 -end note ]

希望您知道机器的寻址结构,并且不会感到惊讶。