使用 pedantic flag 编译时,如何在 C++ 中从 (void *) 重新输入到 int 而不会收到任何警告?

Posted

技术标签:

【中文标题】使用 pedantic flag 编译时,如何在 C++ 中从 (void *) 重新输入到 int 而不会收到任何警告?【英文标题】:How to retype from (void *) to int in C++ without getting any warning when compiling with pedantic flag? 【发布时间】:2013-06-07 11:39:58 【问题描述】:

我有通过sockets 通信的mutlithread 客户端-服务器应用程序。 我用这种结构创建了新线程:

 pthread_t thread;
 pthread_create(&thread, NULL, c->sendMessage, (void *) fd);

其中fd 是连接的ID,c->sendMessage 是一个函数,在创建新线程后调用并处理该线程。在这个函数中,我需要通过send(int sockfd, const void *buf, size_t len, int flags);发送一些消息

所以我这样得到sockfd

void * Client::sendMessage(void *threadid) 
   int sockfd = (int) threadid;
   // some more code here and in the end I send the data via send(int sockfd, const void *buf, size_t len, int flags)

我使用-pedantic 标志进行编译,并且大多数编译器(包括我的)在编译期间不会抛出任何警告或错误。但是有些人在编译过程中抛出一个错误,说从void *int 的重新输入是不安全的,可能会导致loose of precision。我明白,这不是一个好的解决方案,应该做得更干净。但我不知道怎么做。任何人都可以建议我任何干净的做法,如何将 ponter 重新输入为 int 并在编译期间避免任何警告?

【问题讨论】:

如果你此时使用std::thread,这个问题似乎是可以避免的。 是的,这可能是解决方案,如何避免这个问题,但问题不是,如何避免,而是如何解决它:) 【参考方案1】:

发送指针而不是整数有什么问题?将int 转换为void*,或将void* 转换为int,这不是标准的符合解决方案。

pthread_create(&thread, NULL, c->sendMessage, new int(fd));

int* sockfd_ptr = (int*)threadid;
// some usage
delete sockfd_ptr;

任何指针都可以转换为void*,所以它应该可以正常工作。不要忘记在程序的某个位置删除threadid。 可能最好创建一些存储引用/指针的类。

另外,我不明白,你如何将成员函数发送到 C 函数中,这也不正确。

【讨论】:

因为我需要在vectorsmaps 中保存线程ID 才能进一步使用它们,所以这不仅仅是发送消息。是的,将pointers 保存在vector 中也可能有效,但我也很好奇如何解决这个问题,以及为什么有些编译器对此没有任何问题,而有些则有。 new int(fd) 很好,但有人需要delete【参考方案2】:

int 转换为void* 然后再转换回int 是一个非常糟糕的主意,因为C++ 标准中绝对不能保证这两种类型的大小相同。

如果您确实必须在整数类型和指针之间进行转换(这不是一个好主意,但有时没有其他选择),请使用 intptr_t@987654325 @ 而不是 int,因为它们保证与指针大小相同。这样您就不会收到任何警告。

作为旁注,像你这样的传统 C 转换在 C++ 中是不受欢迎的,因为你无法确定它们在幕后做了什么(可能是 static_castreinterpret_cast,谁知道?)。更喜欢使用正确的 C++ 强制转换,即 reinterpret_cast 在您的情况下。

【讨论】:

对我来说,这个问题意味着fd 的类型是外部定义的,没有选择 @BalogPal:啊对,我错过了。但是我担心他们之间没有办法正确地投射。 ForEveR 的解决方案或 PlasmaHH 的评论可能是正确的。 pthread_create 具有固定签名,因此无法更改。但提问者可能会尝试将int 转换为intptr_tv and then to void*`。 @WernerHenze:是的,我只是错过了问题中fd 的类型失控的部分。我的回答确实是解决一个必须pthread_create一样在void*之间进行转换的情况。【参考方案3】:

您可以添加 static_assert(sizeof(fd) <= sizeof(void*), "problem") 之类的内容,并依赖 reinterpret_cast 将在这种情况下往返的实现文档。

【讨论】:

以上是关于使用 pedantic flag 编译时,如何在 C++ 中从 (void *) 重新输入到 int 而不会收到任何警告?的主要内容,如果未能解决你的问题,请参考以下文章

gcc编译选项pedantic(GCC编译器的C++标准严格模式)

是否可以使用 GCC 编译具有特定编译器标志的代码文件的一部分?

如何禁用警告“省略局部变量的类型注释”?在 Dart 中(带有 Pedantic 包)

如何在 Vue 3.0 中通过 Webpack 使用 Bundler Build Feature Flags?

在包“cn.pedant.sweetalert”中找不到属性“ProgressIndeterminate”的资源标识符

如何加快 MonoTouch 编译时间?