【问题标题】:Why can't I call the function (signal handler) returned by function signal?为什么我不能调用函数信号返回的函数(信号处理程序)?
【发布时间】:2019-03-28 04:33:11
【问题描述】:

在弄清楚signal函数的签名后,我修改了https://en.cppreference.com/w/c/program/signal给出的例子。

但是为什么我不能调用signal返回的函数(信号处理程序),而可以直接调用它呢?


void (*signal( int sig, void (*handler) (int))) (int);

signal 函数返回一个指向函数的指针,即void (*)(int)

返回值

上一个信号处理程序成功或SIG_ERR失败(在某些实现上可以禁用设置信号处理程序)。

#include <signal.h>
#include <stdio.h>

void signal_handler(int signal)
{
    printf("hahahah\n");
}

int main(void)
{
    void (*f1)(int);
    f1 = signal(SIGINT, signal_handler);
    f1(3);  //Get signal SIGSEGV and failed
//    signal_handler(3); //OK
    raise(SIGINT);

}

我知道这可能看起来像一个毫无意义的问题,但重点是,f1 指向signal_handler,所以调用f1(3) 就像调用signal_handler(3),我不明白为什么后者可以但不是前者,我认为这两个调用函数语句之间不应该有“技巧”。

【问题讨论】:

  • 前面的信号处理程序不一定是指向函数的指针。
  • @user3386109 嗯,不明白。 signal返回void (*)(int),这不是指向函数的指针(函数指针)并且可以调用吗?
  • 回应编辑:f1 不指向signal_handler。它指向 previous 信号处理程序。您可以使用printf%p 格式说明符来显示f1signal_handler,您会发现它们是不同的。
  • @user3386109 是的,你是对的。感谢您告诉我使用%p :D.

标签: c signals


【解决方案1】:

在下面一行:

f1 = signal(SIGINT, signal_handler);

f1 被分配了一个previous 信号处理程序(在代码中不是signal_handler),它可能不是指向您可以使用int 参数调用的函数的指针。

为了达到您想要的效果,定义第二个信号处理程序并将其分配给上述行之后的f1

类似这样的:

#include <signal.h>
#include <stdio.h>

void signal_handler2(int signal)
{
    printf("hahahah2222\n");
}

void signal_handler(int signal)
{
    printf("hahahah\n");
}

int main(void)
{
    void (*f1)(int);
    f1 = signal(SIGINT, signal_handler);
    f1 = signal(SIGINT, signal_handler2);
    f1(3);  //Success
    signal_handler2(3); //OK
    raise(SIGINT);    
}

输出:

hahahah
hahahah2222
hahahah2222

观看直播Demo

【讨论】:

  • 原来如此.. 文档总是有点误导。既然我已经注册了一个新的处理程序,我自然会认为 previous handler 应该是我刚刚注册的那个......谢谢顺便说一句;)
【解决方案2】:

signal() 可以返回的至少 3 个值不是指向实际函数的指针:

  1. SIG_DFL — 通常是 ((void (*)(int))0)
  2. SIG_IGN — 通常是 ((void (*)(int))1)
  3. SIG_ERR — 通常是 ((void (*)(int))-1)

程序启动时,信号处于SIG_IGNSIG_DFL 模式;您可以随后将它们设置为另一个值。

当您调用f1 = signal(SIGINT, signal_handler); 时,您会返回SIG_DFLSIG_IGN 之一——它们都不是指向可调用函数的指针(即使它们的类型是指向正确类型函数的指针)。

【讨论】:

  • 模式#define HAHA (void(*)(int)) 2是什么意思?我猜它定义了一个函数pointer,指针的值是2。但我只熟悉#define CONSTANT value 这样的模式。我试图通过做#define HAHA float 2.3 来模仿但失败了:(。这是我第一次看到这种用法,你能给我一些提示或者可能是一些参考吗?我看到关于 SO 的其他 2 个问题,但答案不是t 真的很有帮助。
  • 是的; HAHA 是一个数值为 2 的函数指针。它不能安全地用在 (*HAHA)(3)HAHA(3) 中——这两种表示法都有效,但在 C89 标准发布之前,前者是必需的。
  • 好的,我明白了。谢谢。知道在一些官方文档或标准中哪里可以找到这种用法吗?
  • 嗯,符号(void (*)(int)) 后跟一个值是将该值转换为指向函数的指针。铸造2(或10-1)可能在任何地方都没有正式记录。快速浏览 C11 标准并没有发现任何有用的信息。
  • 哦,我明白了。没什么特别的,就是选角。是的,这就是我需要的。那么我绝对可以做到#define HAHA (float) 2.3。谢谢ssssss!
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2016-03-31
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多