关于ISO C标准中signal.h头文件宏定义的技术疑问
根据ISO C N2176_C17_finaldraft文档7.14.3章节,signal.h头文件中定义的宏如下:
定义的宏包括:SIG_DFL、SIG_ERR、SIG_IGN。这些宏会展开为具有不同值的常量表达式,其类型与signal函数的第二个参数及返回值兼容;且它们的值与任何可声明函数的地址均不相等;此外,以下宏会展开为类型为int的正整数常量表达式,值各不相同,代表信号编号,分别对应特定场景:SIGABRT -> 异常终止,比如由abort函数触发;SIGFPE -> 错误算术运算,比如除零或运算溢出;SIGILL -> 检测到无效函数镜像,比如无效指令;SIGINT -> 接收到交互式注意信号;SIGSEGV -> 无效存储访问;SIGTERM -> 发送给程序的终止请求
针对你提出的三个疑问,解答如下:
1. SIG_DFL、SIG_ERR、SIG_IGN的类型确认
你的理解有部分偏差:这些宏的类型确实与void (*)(int)兼容(可直接赋值给该类型的函数指针变量,或作为signal()函数的参数/返回值使用),但它们不是实际的函数地址。标准明确说明它们的值与任何可声明函数的地址都不相等,本质是编译器实现的特殊常量值,用来标记“默认处理”“错误”“忽略信号”这三种特殊行为。
2. “可声明函数”的定义
这里的“可声明函数”指任何符合C语法规则能合法声明的函数——不管是你编写的自定义函数、标准库提供的函数,还是编译器内置函数。这条规定是为了保证SIG_DFL、SIG_ERR、SIG_IGN的取值不会和任何普通函数的指针值冲突,避免程序将其误判为某个函数的地址。
3. 信号编号宏的含义解释
第三条说明的是另一类宏(SIGABRT、SIGFPE等)的用途:
- 这些宏都是
int类型的正整数常量,每个对应唯一的信号编号; - 每个信号编号对应程序运行时可能遇到的特定事件:
SIGABRT:调用abort()函数时触发,用于强制程序异常终止;SIGFPE:发生算术错误时触发,比如除以零、整数溢出、浮点数运算错误等;SIGILL:CPU检测到无效指令时触发,比如程序执行了不符合当前架构的机器码;SIGINT:程序接收到交互式中断信号时触发,比如用户在终端按下Ctrl+C;SIGSEGV:程序试图访问非法内存地址时触发,比如访问空指针、越界访问数组;SIGTERM:收到外部终止请求时触发,比如通过kill命令向程序发送终止信号。
这些信号编号是程序与操作系统传递事件通知的标准标识,你可以通过signal()函数为其绑定自定义处理函数,或指定默认/忽略行为。
内容的提问来源于stack exchange,提问作者user20333834

