C语言中基于参数类型的专用宏扩展

ux6nzvsh  于 2022-12-03  发布在  其他
关注(0)|答案(1)|浏览(162)

我有一个函数,它的参数是uint32_t *,它实际上指向一个64位的值。我想在它周围有一个宏,它接受uint64_t作为输入。
宏是否可以根据其输入参数类型进行不同的扩展?
下面的宏对我的情况很有效;但是,它效率不高:

void func(uint32_t* a);

#define func_wrapper(a) do { \
    uint64_t aa = a; func((uint32_t*) &aa); \
} while(0)

例如,情况1不如下面的情况3有效。

uint64_t x = 12;
func_wrapper(x)        // case 1
func_wrapper(12)       // case 2
func((uint32_t*) &x);  // case 3

有没有办法定义一个宏,它扩展到

#define func_wrapper(a) { \
    func((uint32_t*) &(a)); \
}

当参数不是常值且扩充为

#define func_wrapper(a) { \
    uint64_t aa = a; func((uint32_t*) &(aa)); \
}

什么时候?

pod7payv

pod7payv1#

C宏完全在预处理阶段进行处理,该阶段缺少类型信息,并且不能基于语言概念(如类型)进行不同的扩展。C语言提供的多态性工具非常少,而这似乎正是您实际需要的。
值得一提的是,通过uint32_t*类型的指针访问有效类型为uint64_t的值会破坏C's type-aliasing rules。这是一个非常糟糕的想法,可能会导致各种未定义的行为,尤其是在存在高级别编译器优化的情况下。
现在来谈谈你问题中的基本假设,我想回答以下问题:
例如,情况1的效率不如情况3
下面是宏扩展后的代码,我也在其中修复了类型别名冲突:

void func(uint64_t* a);

uint64_t x = 12;
uint64_t aa = x; func((uint64_t*) &aa); // case 1
func((uint64_t*) &x);                   // case 3

您不应该假设情况3在运行时比情况1更有效。C优化器能够进行一些非常激进的优化,最终优化的可执行文件中的指令/周期数与C语言中的语句数只有微弱的相关性。在本例中,如果编译器能够证明func没有修改其参数,那么它就可以应用copy propagation并完全删除临时变量aa。假设该属性为true,您可以通过使用const限定符声明func来帮助分析完成此操作,即:

void func(const uint64_t* a);

然而,即使没有任何优化,您也不太可能在现代超标量处理器上测量这些处理器之间的真实的性能差异。

相关问题