【发布时间】:2016-09-20 00:32:23
【问题描述】:
此问题与Warning (Anachronism): Assigning void(*)(int) to extern "C" void(*)(int) 有关。在引用的问题中,我们有一个函数指针 typedef 声明为 extern "C":
extern "C" {
typedef void (*SignalHandlerFn) (int);
};
当我们尝试分配它时:
new_handler.sa_handler = (pfn ? reinterpret_cast<SignalHandlerFn>(pfn) :
reinterpret_cast<SignalHandlerFn>(defaultHandler));
它导致了错误(行号有点偏离,但上面的行产生了它):
/opt/solarisstudio12.4/bin/CC -DDEBUG -c test.cpp
...
"ossig.h", line 75: Warning (Anachronism): Using void(*)(int) to initialize extern "C" void(*)(int).
"test.cpp", line 135: Where: While instantiating "SignalHandler<5, 0>::SignalHandler(extern "C" void(*)(int), int)".
"test.cpp", line 135: Where: Instantiated from non-template code.
2 Warning(s) detected.
据我所知,extern "C" 在使用 reinterpret_cast 时被丢弃了。但是,C 转换按预期工作。
我相信 Sun Studio 12.4 (SunCC 5.13) 默认使用 C++03。但我的问题同时适用于 C++03 和 C++11,因为由于 GCC 4.8 和 4.9 的流行,我们现在看到了很多。
C++ 强制转换是否会从声明中去除 extern "C"?
solaris:~$ cat test.cxx
#include <signal.h>
extern "C" {
typedef void (*SignalHandlerFn) (int);
};
template <int S, bool O=false>
struct SignalHandler
{
SignalHandler(SignalHandlerFn pfn = NULL, int flags = 0) : m_installed(false)
{
struct sigaction new_handler;
do
{
int ret = 0;
ret = sigaction (S, 0, &m_old);
if (ret != 0) break; // Failed
if (m_old.sa_handler != 0 && !O) break;
new_handler.sa_handler = (pfn ? reinterpret_cast<SignalHandlerFn>(pfn) :
reinterpret_cast<SignalHandlerFn>(&SignalHandler::NullHandler));
new_handler.sa_flags = (pfn ? flags : 0);
ret = sigemptyset (&new_handler.sa_mask);
if (ret != 0) break; // Failed
ret = sigaction (S, &new_handler, 0);
if (ret != 0) break; // Failed
m_installed = true;
} while(0);
}
~SignalHandler()
{
if (m_installed)
sigaction (S, &m_old, 0);
}
private:
struct sigaction m_old;
bool m_installed;
static void NullHandler(int /*unused*/) { /* continue*/ }
private:
// Not copyable
SignalHandler(const SignalHandler &);
void operator=(const SignalHandler &);
};
int main(int argc, char* argv[])
{
SignalHandler<SIGTRAP, 0> handler;
return 0;
}
【问题讨论】:
-
语言链接是函数类型的一部分(你可以重载它);不幸的是,大多数编译器都没有正确实现这一点。
-
谢谢克雷克。这是否意味着 SunCC 是正确的,我的
SignalHandlerFn是错误的,其他编译器应该拒绝它?或者这是否意味着 SunCC 处理不当?不好意思问。我知道如何解决它;但我仍然不清楚问题是什么。 -
您的
NullHandler肯定是错误的,因为类成员函数从来没有C 链接。事实上,GCC 和 Clang 完全忽略了这一点。您可以仔细检查 Embarcadero,我相信它正确地实施了这些规则。另一方面,pfn应该是正确的。
标签: c++ linkage reinterpret-cast