当前位置: 首页 > 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.jsqmd.com/news/544841/

相关文章:

  • nli-distilroberta-base精彩案例分享:复杂嵌套句式下的中立关系精准捕获
  • Python函数式编程:从原理到实践
  • Arthas进阶技巧:trace匿名函数的完整指南(含常见问题解决方案)
  • 英飞凌TC3xx STM中文开发指导手册
  • 颠覆式条码生成方案:Libre Barcode让字体成为你的条码工具库
  • 2026广州装修公司优质推荐指南 - 真知灼见33
  • 别再对着88个变量发愁了!手把手教你从FNL grib2文件中精准揪出UV风场(附NCL代码)
  • 深入SOEM内核:从EEPROM/SII访问到过程数据同步,揭秘EtherCAT主站高效通信的底层逻辑
  • Java 中的 5 大 AI 框架:介绍及功能、优势全方面对比
  • Gartner:超一半企业在RPA落地12个月内想换方案——问题不在技术,在选型逻辑
  • 原圈科技GEO:不懂会落后,AI营销如何赢得下半场?
  • AI元人文:意义场域中的自感养护 ——基于20世纪哲学转向与21世纪元理论的体系性建构
  • 2026国产直读光谱仪推荐,硬核质量护航检测,高性价比优选钢研纳克 - 品牌推荐大师
  • 温度冲击试验箱行业全景与国内外知名厂家top5推荐(2026最新分析) - 品牌推荐大师
  • 谢赛宁访谈深度摘录:当变量成为路径
  • UE5蓝图节点Break Hit Result实战:如何精准获取碰撞信息(附VR游戏案例)
  • AMD GPU专属优化:Ollama-for-amd本地大模型部署终极指南
  • UE5蓝图入门别再死记硬背了!保姆级实战拆解:从动画状态机到AI行为树,手把手带你避坑
  • 键盘固件定制完全指南:从零开始的个性化配置之旅
  • 终极指南:如何用Zotero Style插件实现文献管理效率提升200%
  • v2.cn.vuejs.org:面向中文开发者的Vue.js 2技术文档解决方案
  • 5个技巧掌握Cherry Studio:一站式AI服务的多模型管理实践
  • 2026年深圳全屋净水品牌综合竞争力深度评测:五大服务商如何破局家庭用水痛点? - 2026年企业推荐榜
  • 基于PLC1200的水箱液位解耦控制系统(过程控制课程设计) #笔记学习资料 内含: 1
  • 2026苏州吴中区高性价比装修公司TOP10推荐 口碑好、资质正规工装、家装、别墅、毛坯房装修公司精选 - 品牌智鉴榜
  • GD32E230 ADC数据错位?一个开关引发的‘血案’与修复实录
  • Auto.js进阶:用贝塞尔曲线模拟更‘像人’的滑动手势(防检测实战)
  • 2026兰州学美甲去哪?城关/七里河正规机构选校参考,艺丽美妆值得考察 - 梅1梅
  • 浏览器端图像修复技术突破:Inpaint-web如何通过WebGPU与WASM实现专业级图像处理
  • 墨语灵犀在互联网产品设计中的应用:用户需求分析与PRD生成