C11中如何对typedef定义的结构体使用_Generic实现函数重载
问题1:按值传递结构体的版本编译报错的原因
_Generic的核心运行规则是:仅会选择与参数类型匹配的分支执行,但所有分支的表达式都会被编译器做完整的类型与语法校验,未被选中的分支也不能出现编译错误。
你当前的宏定义是把参数传递直接写在了每个分支里:
#define func(param)\ _Generic((param),\ Args_int: func_int(param),\ Args_char: func_char(param));
当你传入Args_char类型的参数时,Args_int: func_int(param) 这个分支里,相当于要把Args_char类型的变量传给只接受Args_int类型的func_int函数,类型完全不兼容,直接触发编译错误,哪怕这个分支永远不会被_Generic选中也没用。
修复方案
把参数传递逻辑挪到_Generic表达式外部,分支仅返回对应匹配的函数指针即可:
#define func(param)\ _Generic((param),\ Args_int: func_int,\ Args_char: func_char\ )(param)
这样_Generic只会根据参数类型选择对应的函数,选完之后再统一传入参数,未被选中的分支仅涉及函数名的引用,不会出现参数类型不匹配的问题,编译即可通过。
问题2:结构体指针版本能正常运行是否是偶然
不是偶然,但属于编译器宽松检查下的侥幸可运行写法,本质上和值传递版本有相同的问题。
C标准本身不允许不同类型的结构体指针互相传递,但很多编译器默认情况下对指针类型不兼容的情况只会输出警告,不会直接终止编译。你如果开启严格编译选项(比如gcc -Wall -Werror),指针版本一样会报类型不兼容的错误。
你当前的指针版本能跑通,只是因为编译器没有把指针类型不兼容的问题升级为错误,属于不符合C标准规范的写法,不建议沿用,同样建议改成上面提到的「分支返回函数指针、外部统一传参」的写法。
内容的提问来源于stack exchange,提问作者ptk
相关产品推荐
相关产品推荐

