警告(不合时宜):将void(*)(int)赋给extern“C”void(*)(int)

时间:2016-09-18 19:54:20

标签: c++ function-pointers solaris linkage sunstudio

我在使用Sun的C ++编译器时遇到了麻烦。我读过Oracle的Working with Pointers to Functions [from C++]。这是一个很好的阅读,我得到的印象是SunCC在该领域的所有编译器中最为合规(尽管它给我带来了麻烦)。

测试代码如下,第24行是new_handler.sa_handler = (pfn ? pfn : &SignalHandler::NullHandler);。展开三元运算符会显示问题:new_handler.sa_handler = pfn;

SunCC 5.11

$ /opt/solstudio12.2/bin/CC test.cxx
"test.cxx", line 24: Warning (Anachronism): Assigning void(*)(int) to extern "C" void(*)(int).
"test.cxx", line 58:     Where: While instantiating "SignalHandler<5, 0>::SignalHandler(void(*)(int), int)".
"test.cxx", line 58:     Where: Instantiated from non-template code.

SunCC 5.12

$ /opt/solarisstudio12.3/bin/CC test.cxx
"test.cxx", line 24: Warning (Anachronism): Assigning void(*)(int) to extern "C" void(*)(int).
"test.cxx", line 58:     Where: While instantiating "SignalHandler<5, 0>::SignalHandler(void(*)(int), int)".
"test.cxx", line 58:     Where: Instantiated from non-template code.

SunCC 5.13

$ /opt/solarisstudio12.4/bin/CC test.cxx
"test.cxx", line 24: Warning (Anachronism): Using void(*)(int) to initialize extern "C" void(*)(int).
"test.cxx", line 58:     Where: While instantiating "SignalHandler<5, 0>::SignalHandler(void(*)(int), int)".
"test.cxx", line 58:     Where: Instantiated from non-template code.

SunCC 5.14

$ /opt/developerstudio12.5/bin/CC test.cxx
$

我不清楚问题是什么。这是Oracle板上的类似问题,但OP基本上告诉RTFM:Sun Studio 11 "Warning (Anachronism)"

如何解决不合时宜的警告?

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 ? pfn : &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;
}

2 个答案:

答案 0 :(得分:2)

您可以将SignalHandler :: NullHandler更改为常规C函数(我们将其命名为SignalHandler_NullHandler)。 然后在外部“C”中包装SignalHandler_NullHandler和SignalHandlerFn。

顺便说一句。我猜测如何“对齐”这两个函数,但是你在评论中更好地解释了C / C ++的存在问题。

答案 1 :(得分:1)

在表达式中:

pfn ? pfn : &SignalHandler::NullHandler

第二个和第三个操作数具有不同的类型(因为一个指向具有“C”语言链接的函数,一个指向具有“C ++”语言链接的函数);并且没有隐式转换可以改变语言链接。

因此表达形式不正确。另一个答案建议使用强制转换,但这可能会在运行时以静默未定义行为为代价来抑制诊断:通过指向不同类型函数的指针调用函数。

当然,特定编译器可能会在C ++标准未定义的任何场景中提供扩展来定义行为。 (或者碰巧“无论如何都要工作”)。

我的建议是将SignalHandler::NullHandler替换为具有C语言链接的函数。这不能是类成员,因为语言语法阻止extern "C"出现在类定义中。