当前位置: 首页 > news >正文

C语言的重载——变参函数

背景

最近项目中需要用到posix消息队列,查看其API,发现mq_open函数比较特殊,竟然有2个同名的函数签名:

mqd_tmq_open(constchar*name,intoflag);mqd_tmq_open(constchar*name,intoflag,mode_tmode,structmq_attr*attr);

我记得C语言是不支持函数重载的,这是怎么做到的呢?

分析

这应该是在链接阶段耍的花招😕

弱别名

一开始以为是弱别名机制,但是看完这篇文章后感觉并不能解答问题

严格别名

又翻到这篇文章,感觉更不相关。

翻glibc源码

glibc的源码文件
rt/bits/mqueue2.h

sysdeps/unix/sysv/linux/mq_open.c
里找到了答案,原来是通过变参函数来实现的运行时“重载”

声明

rt/bits/mqueue2.h
检查第二个参数oflags,如果O_CREAT置位,则调用4参数版本,否则调用2参数版本:

externmqd_tmq_open(constchar*__name,int__oflag,...)__THROW__nonnull((1));externmqd_t__mq_open_2(constchar*__name,int__oflag)__THROW__nonnull((1));externmqd_t__REDIRECT_NTH(__mq_open_alias,(constchar*__name,int__oflag,...),mq_open)__nonnull((1));__errordecl(__mq_open_wrong_number_of_args,"mq_open can be called either with 2 or 4 arguments");__errordecl(__mq_open_missing_mode_and_attr,"mq_open with O_CREAT in second argument needs 4 arguments");__fortify_functionmqd_t__NTH(mq_open(constchar*__name,int__oflag,...)){if(__va_arg_pack_len()!=0&&__va_arg_pack_len()!=2)__mq_open_wrong_number_of_args();if(__builtin_constant_p(__oflag)){if((__oflag&O_CREAT)!=0&&__va_arg_pack_len()==0){__mq_open_missing_mode_and_attr();return__mq_open_2(__name,__oflag);}return__mq_open_alias(__name,__oflag,__va_arg_pack());}if(__va_arg_pack_len()==0)return__mq_open_2(__name,__oflag);return__mq_open_alias(__name,__oflag,__va_arg_pack());}

实现

sysdeps/unix/sysv/linux/mq_open.c
__mq_open是4参数版本,__mq_open_2是2参数版本,其实就是将第三第四个参数置空,然后传给4参数版本。

mqd_t__mq_open(constchar*name,intoflag,...){if(name[0]!='/')returnINLINE_SYSCALL_ERROR_RETURN_VALUE(EINVAL);mode_tmode=0;structmq_attr*attr=NULL;if(oflag&O_CREAT){va_list ap;va_start(ap,oflag);mode=va_arg(ap,mode_t);attr=va_arg(ap,structmq_attr*);va_end(ap);}returnINLINE_SYSCALL(mq_open,4,name+1,oflag,mode,attr);}strong_alias(__mq_open,mq_open);mqd_t__mq_open_2(constchar*name,intoflag){if(oflag&O_CREAT)__fortify_fail("invalid mq_open call: O_CREAT without mode and attr");return__mq_open(name,oflag);}

验证

给mq_open传递3个参数,编译链接通过,说明glibc确实用的变参函数,否则编译一定通不过。

#include<stdio.h>#include<stdlib.h>#include<fcntl.h>#include<sys/stat.h>#include<mqueue.h>mqd_tq;intmain(){q=mq_open("/mq",O_CREAT,S_IRWXU);return0;}

神奇的是,运行时也未抛出异常。

后记

其实openopenat系统调用也是通过变参函数实现的函数重载效果😉

http://www.cnnetsun.cn/news/1517754.html

相关文章:

  • 工业大数据价值究竟在哪?不只是分析,更是精准决策与执行
  • py每日spider案例之随即视频接口获取
  • 利用快马平台快速生成vmware workstation开发环境原型,十分钟搭建测试沙箱
  • 本地部署开源 PDF 工具箱 Stirling-PDF 并实现外部访问( Windows 版本)
  • 告别黑屏!Jetson CSI摄像头gst-launch-1.0与OpenCV常见报错排查与性能调优指南
  • 实际如何编写用例
  • PXC集群节点异常关闭后如何快速恢复?手把手教你排查grastate.dat文件
  • 颠覆式PS4游戏体验:GoldHEN Cheats Manager一站式作弊代码管理解决方案
  • 像素时装锻造坊应用场景:AR滤镜开发中像素化虚拟时装实时渲染预演
  • Qwen3.5-4B-Claude-Opus应用场景:技术博客选题生成、文章大纲结构化输出
  • 【数据结构与算法】最小生成树-SPFA
  • 从OSEK到AUTOSAR:汽车网络管理演进史,为什么现在主流是AUTOSAR NM?
  • GTE中文-large效果展示:中文古诗文本中意象实体识别+情感基调(豪放/婉约)分类结果
  • 【AI】API 调用基础:执行式AI必备网络请求知识
  • WinAsar:一站式图形化asar文件管理解决方案
  • 3倍提速!LightGBM梯度提升框架的终极性能优化指南
  • AllinAI:企业必须关注的7个网络安全技术发展趋势
  • 像素幻梦·创意工坊实操手册:自定义LoRA训练数据集构建与注入流程
  • Visual Studio项目创建指南
  • 【水下图像增强】U形Transformer:从全局建模到多尺度融合的增强实践
  • GCC 4.8+环境下ASAN内存检测实战:从编译选项到日志分析全流程
  • ESP32蓝牙Notify传数据,为啥总丢包?手把手教你调MTU和避坑
  • 快速掌握CREST:药物研发中分子构象采样的完整指南
  • 大模型入门必看:小白程序员轻松掌握AI的“大脑”与“工作”之道,速收藏!
  • 避坑指南:HDevelop开发中90%人会遇到的5个变量管理问题(附解决方案)
  • 天津智能装备工厂如何5个SolidWorks研发共用一台工作站
  • Windows 10 + PyCharm 环境下,YOLACT训练自己的数据集全流程避坑指南(附中断训练恢复技巧)
  • Qwen3-Reranker-0.6B性能测试:低延迟高并发的企业级服务
  • 照着用就行:2026 最新降AI率网站深度测评与推荐
  • Flink管理界面密码保护避坑指南:从HTTPD安装到Nginx配置全流程