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

如何获取指针指向的数据类型?求类似typeof的typeof_ptr实现方案

当然可以实现!

要在编译时提取指针(不管是一级还是多级)最终指向的类型,我们可以借助C语言的预处理器宏结合编译器的类型推导扩展来实现你要的typeof_ptr工具。下面分两种场景给出实现方案,适配不同的编译器和标准:

方案一:兼容C11及以上(利用_Generic)

这种方法更安全,依赖C11标准的_Generic特性,同时借助GCC/Clang的__builtin_types_compatible_p扩展来判断类型是否为指针:

#include <stdio.h>

// 判断类型是否为指针(支持const/volatile修饰)
#define IS_POINTER(T) \
    __builtin_types_compatible_p(T, void*) || \
    __builtin_types_compatible_p(T, const void*) || \
    __builtin_types_compatible_p(T, volatile void*) || \
    __builtin_types_compatible_p(T, const volatile void*)

// 递归剥离指针层,直到得到非指针类型
#define typeof_ptr_recursive(T) \
    _Generic((T), \
        void*: void, \
        const void*: const void, \
        volatile void*: volatile void, \
        const volatile void*: const volatile void, \
        default: IS_POINTER(typeof(*(T*)0)) ? typeof_ptr_recursive(typeof(*(T*)0)) : typeof(*(T*)0) \
    )

// 对外暴露的工具宏:先获取变量类型,再递归剥离指针
#define typeof_ptr(p) typeof_ptr_recursive(typeof(p))

// 测试示例
typedef struct {
    int x;
} struct_t;

int main() {
    struct_t *pointer1;
    struct_t **pointer2;
    struct_t ***pointer3; // 甚至三级指针也能处理

    typeof_ptr(pointer1) a; // a 的类型是 struct_t
    typeof_ptr(pointer2) b; // b 的类型是 struct_t
    typeof_ptr(pointer3) c; // c 的类型是 struct_t

    // 验证类型有效性:直接访问结构体成员
    a.x = 10;
    b.x = 20;
    c.x = 30;

    printf("a.x = %d, b.x = %d, c.x = %d\n", a.x, b.x, c.x);
    return 0;
}

原理说明

  1. typeof(p)先获取输入变量的类型(比如struct_t**);
  2. typeof_ptr_recursive通过_Generic判断当前类型是否为指针:
    • 如果是指针类型,就递归处理该指针指向的类型(比如struct_t**指向的是struct_t*,继续递归);
    • 如果是非指针类型,就直接返回该类型;
  3. 整个过程完全在编译期完成,不会产生任何运行时代码,也不会有指针解引用的风险。

方案二:GCC/Clang专属(简化递归版)

如果你只需要适配GCC或Clang这类支持typeof扩展的编译器,可以用更简洁的递归宏实现:

#include <stdio.h>

#define IS_POINTER(T) \
    __builtin_types_compatible_p(T, void*) || \
    __builtin_types_compatible_p(T, const void*) || \
    __builtin_types_compatible_p(T, volatile void*) || \
    __builtin_types_compatible_p(T, const volatile void*)

#define typeof_ptr(p) \
    IS_POINTER(typeof(p)) ? typeof_ptr(*(p)) : typeof(p)

// 测试示例同方案一
typedef struct {
    int x;
} struct_t;

int main() {
    struct_t *pointer1;
    struct_t **pointer2;

    typeof_ptr(pointer1) a;
    typeof_ptr(pointer2) b;

    a.x = 10;
    b.x = 20;
    printf("a.x = %d, b.x = %d\n", a.x, b.x);
    return 0;
}

注意事项

  • 这些方案依赖编译器扩展(typeof、__builtin_types_compatible_p)或C11标准特性,标准C(C99及更早)没有原生支持typeof,但大部分现代编译器都提供了这些扩展;
  • 所有操作都在编译期完成,不会有运行时的性能开销或空指针访问风险;
  • 如果你的场景只需要处理最多两级指针,也可以用更简单的宏:#define typeof_ptr(p) typeof(**(1 ? &p : (void*)0))(注意这个只适用于≤2级指针)。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.21 07:25:22