ML_EXTERN _ML_AB ML_FUNC(M_Process)
#ifdef ML_ARGS_LIST
(
ML_INT i
);
#endif
如果我为供应商(需要实现这些接口)创建接口,为什么我的 API 中会有上述声明?我认为它被称为宏-为什么我不将函数声明为“正常”:int M_Process();
?有什么区别,上面声明的各个部分有什么作用?
ML_EXTERN _ML_AB ML_FUNC(M_Process)
#ifdef ML_ARGS_LIST
(
ML_INT i
);
#endif
如果我为供应商(需要实现这些接口)创建接口,为什么我的 API 中会有上述声明?我认为它被称为宏-为什么我不将函数声明为“正常”:int M_Process();
?有什么区别,上面声明的各个部分有什么作用?
像这样的宏主要是为了与不同的 C 编译器兼容而添加的。您会在 1980 年代和 1990 年代的代码中发现这一点,这些编译器要么兼容 K&R(早于 ANSI C),要么缺乏各种特性。
您必须阅读宏定义才能绝对确定,但是这种事情有一些常见的模式。宏分为几种类型:
通过定义ML_EXTERN
,API 可以支持不同的调用约定(例如,stdcall、fastcall 等),或不同类型的外部链接(例如,Microsoft 的dllexport
)。这提供了编译器兼容性和跨平台兼容性,同时不会显着影响代码的可读性。
int
、short
和等类型中的位数long
取决于平台,尽管有一些限制。许多早于标准inttypes.h
和stdint.h
头文件的库都使用宏或 typedef 来确保它们的类型在所有平台上都是相同的大小。 ML_INT
是宏或 typedef 到适当大小的整数类型。
80 年代的许多编译器都是按照 C 的 K&R 标准构建的,不支持 ANSI 函数原型。ML_FUNC
和ML_ARGS_LIST
宏解决了这个问题 。
如果支持原型,ML_ARGS_LIST
则将定义并ML_FUNC(x)
扩展为x
. 完全扩展,忽略ML_EXTERN
and_ML_AB
将是:
M_Process(ML_INT i)
如果编译器不支持原型,ML_FUNC(x)
则将展开为x()
并省略原型参数列表。完整的扩展将是:
M_Process()
在 K&R C 中,所有参数都根据规则强制执行,参数变量在定义函数的地方定义,而不是声明。有关C 版本差异的一些详细信息,请参阅Wikipedia 关于 C 的条目。