You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

兼容GNU C与C23的deprecated属性宏改写问题

兼容C23的deprecated属性宏解决方案

问题背景

我在使用下述宏时遇到兼容性问题:

// Assume that __GNUC__ or __clang__ is defined. 

#if defined(__has_c_attribute)
    #if __has_c_attribute(deprecated)
        #define ATTRIBUTE_DEPRECATED(...)          [[deprecated(__VA_ARGS__)]]
    #endif    /* deprecated */
#else  
    #define ATTRIBUTE_DEPRECATED(...)              __attribute__((deprecated(__VA_ARGS__)))
#endif    /* __has_c_attribute */

核心矛盾

  • GNU C扩展中,__attribute__((deprecated())) 和 __attribute__((deprecated)) 等价,空参数列表被允许
  • C23标准属性语法中,[[deprecated()]] 是非法写法,无参数时必须写成 [[deprecated]](不能带括号)

现有问题

使用std=c2x编译时,调用ATTRIBUTE_DEPRECATED()会触发报错:

deprecated.c:12:14: error: parentheses must be omitted if attribute argument list is empty

而在未定义__has_c_attribute的环境中,以下两种调用形式均可正常工作:

ATTRIBUTE_DEPRECATED()
ATTRIBUTE_DEPRECATED("private")

需求

  1. 让代码同时兼容C23标准
  2. 支持无需参数时直接写ATTRIBUTE_DEPRECATED(不带括号)

解决方案

通过宏重载区分无参数和带参数场景,实现跨标准兼容:

最终兼容宏实现

// Assume that __GNUC__ or __clang__ is defined. 

#if defined(__has_c_attribute) && __has_c_attribute(deprecated)
    // 针对C23属性语法,区分有无参数分支
    #define ATTRIBUTE_DEPRECATED(...) _ATTRIB_DEPRECATED_CHOOSER(__VA_ARGS__, _WITH_ARG, _NO_ARG)(__VA_ARGS__)
    #define _ATTRIB_DEPRECATED_CHOOSER(_1, _2, NAME, ...) NAME
    #define _NO_ARG() [[deprecated]]
    #define _WITH_ARG(msg) [[deprecated(msg)]]
#else
    // 针对GNU扩展,保留原有逻辑(空参数列表被允许)
    #define ATTRIBUTE_DEPRECATED(...) __attribute__((deprecated(__VA_ARGS__)))
#endif

调用示例

三种调用方式均被支持:

ATTRIBUTE_DEPRECATED int old_func1(void);               // 无参数无括号
ATTRIBUTE_DEPRECATED() int old_func2(void);             // 无参数带括号
ATTRIBUTE_DEPRECATED("use new_func instead") int old_func3(void); // 带参数

原理说明

  1. C23分支:
    • 借助__VA_ARGS__和宏选择器_ATTRIB_DEPRECATED_CHOOSER,根据传入参数数量自动匹配对应展开逻辑
    • 无参数(包括ATTRIBUTE_DEPRECATED())时展开为[[deprecated]],带参数时展开为[[deprecated(msg)]]
  2. GNU分支:
    • 保留原有写法,因为GNU扩展允许__attribute__((deprecated()))这种空参数形式
  3. 无括号调用支持:
    • 直接写ATTRIBUTE_DEPRECATED时,__VA_ARGS__为空,宏选择器会匹配到_NO_ARG,最终展开为合法的无参数属性

验证用例

以下代码可同时兼容GNU模式和C23标准编译:

// 上述兼容宏代码放在此处

ATTRIBUTE_DEPRECATED int min(int a, int b)
{
    return a < b ? a : b;
}

ATTRIBUTE_DEPRECATED() int max(int a, int b)
{
    return a > b ? a : b;
}

ATTRIBUTE_DEPRECATED("use min/max from stdlib") int old_compare(int a, int b)
{
    return a - b;
}

int main() {
    return min(10, 20) + max(5, 15) + old_compare(3, 7);
}

内容的提问来源于stack exchange,提问作者Madagascar

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.29 02:47:39