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

_Generic能否匹配类型名称字符串?

解决方案

针对你提到的「根据类型名称分支处理构造逻辑」的需求,宏字符串化确实是可行的思路,但要结合C语言的预处理特性或C11的类型泛型来实现,以下是几种实用方案:

1. 已知类型变体:用C11类型泛型(最可靠)

如果Point的变体(如Point__alloca、Point__boehm)是提前确定的,用_Generic实现静态类型分支比字符串化更直接,编译期就能完成类型匹配,性能更高:

// 先实现各类型的构造函数
Point__alloca* create_Point__alloca() {
    return (Point__alloca*)alloca(sizeof(Point__alloca));
}

Point__boehm* create_Point__boehm() {
    return (Point__boehm*)boehm_alloc(sizeof(Point__boehm));
}

// 核心new宏,自动匹配类型对应的构造逻辑
#define new(T) _Generic((T){0}, \
    Point__alloca*: create_Point__alloca(), \
    Point__boehm*: create_Point__boehm(), \
    default: NULL /* 未知类型的默认处理 */ \
)

// 使用示例
Point__alloca* p1 = new(Point__alloca);
Point__boehm* p2 = new(Point__boehm);

2. 匹配含"int"的类型:预处理字符串化+静态检测

如果需要对所有名称包含"int"的类型统一处理,可以结合字符串化宏和预处理技巧实现静态判断(注:C预处理无原生字符串包含检测,需借助宏拼接技巧):

基础字符串化宏

#define STRINGIFY(x) #x
#define TYPE_NAME(T) STRINGIFY(T)

预处理阶段检测类型名是否含"int"

// 辅助宏:通过拼接判断字符串是否包含"int"
#define CHECK_INT_IN_NAME(str) str##_int_marker_
#define HAS_INT(T) \
    (sizeof(CHECK_INT_IN_NAME(TYPE_NAME(T))) != sizeof(""_int_marker_))

原理:如果类型名称包含"int",拼接后的字符串长度会比""_int_marker_长,反之则相等。

分支处理的new宏

// 含"int"类型的通用构造逻辑
#define create_int_type(T) ((T*)malloc(sizeof(T)))
// 其他类型的构造示例
#define create_default_type(T) ((T*)calloc(1, sizeof(T)))

#define new(T) \
    _Generic((T){0}, \
        default: HAS_INT(T) ? create_int_type(T) : create_default_type(T) \
    )

这种方式的局限性:仅能处理"int"连续出现的场景,且依赖编译器支持预处理阶段的字符串常量sizeof判断。

3. 运行时动态匹配:字符串化+字符串比较

如果需要更灵活的动态分支(比如支持新增类型无需修改宏),可以结合字符串化和strstr/strcmp实现运行时判断:

#include <string.h>

#define new(T) \
    ({ \
        void* ptr = NULL; \
        const char* type_str = TYPE_NAME(T); \
        if (strstr(type_str, "int") != NULL) { \
            ptr = malloc(sizeof(T)); \
        } else if (!strcmp(type_str, "Point__alloca")) { \
            ptr = alloca(sizeof(T)); \
        } else if (!strcmp(type_str, "Point__boehm")) { \
            ptr = boehm_alloc(sizeof(T)); \
        } \
        (T*)ptr; \
    })

这种方式兼容性好,但属于运行时判断,性能略低于静态分支,且编译期无法做类型检查优化。

关键注意点
  • 预处理阶段的操作都是静态的,无法处理运行时生成的类型名称。
  • _Generic是C11标准特性,需确保编译器支持(如GCC、Clang、MSVC 2015及以上版本)。
  • 字符串化宏#x对大小写敏感,注意类型名称的拼写一致性。

内容的提问来源于stack exchange,提问作者Olle Härstedt

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.09 19:25:28