Dav*_* O. 16 c naming-conventions
大家好,我最近学会用C编程!(这对我来说是一个巨大的进步,因为C++是第一种语言,我接触并吓唬了我近10年.)来自大多数OO背景(Java + C#),这是一个非常好的范式转换.
我爱C.这是一种如此美丽的语言.令我感到惊讶的是,高级的模块化和代码可重用性C支持 - 当然它不像OO语言那么高,但仍远远超出我对命令式语言的期望.
如何防止客户端代码与C库代码之间的命名冲突?在Java中有包,在C#中有命名空间.想象一下,我写了一个C库,它提供了"添加"操作.客户端很可能已经使用了类似的操作 - 我该怎么办?
我特别想找一个客户友好的解决方案.例如,我不想为我的所有api操作添加前缀,例如"myuniquelibname_add".C世界中有哪些常见的解决方案?你把所有api操作放在一个结构中,所以客户端可以选择自己的前缀吗?
我非常期待通过你的答案得到的见解!
亲爱的Answerers,谢谢你的答案!我现在看到,前缀是安全避免命名冲突的唯一方法.所以,我想修改我的问题:我有什么可能,让客户选择他自己的前缀?
Unwind发布的答案是单向的.它不使用正常意义上的前缀,但必须在每个api调用前加上"api->".还有哪些解决方案(比如使用#define)?
这一切归结为两种方法之一:
我不接受任何答案,因为我认为没有正确的答案.选择的解决方案取决于具体情况和自己的偏好.我自己会尝试你提到的所有方法,找出最适合我的方法.随意在相应答案的评论中发布支持或反对某些appraoches的论据.
最后,我要特别感谢:
如果有人发现关闭这个问题是合适的(因为没有进一步的见解),他/她应该随意这样做 - 我无法决定这一点,因为我不是C大师.
unw*_*ind 10
Ken提到的结构方式看起来像这样:
struct MyCoolApi
{
int (*add)(int x, int y);
};
MyCoolApi * my_cool_api_initialize(void);
Run Code Online (Sandbox Code Playgroud)
然后客户会这样做:
#include <stdio.h>
#include <stdlib.h>
#include "mycoolapi.h"
int main(void)
{
struct MyCoolApi *api;
if((api = my_cool_api_initialize()) != NULL)
{
int sum = api->add(3, 39);
printf("The cool API considers 3 + 39 to be %d\n", sum);
}
return EXIT_SUCCESS;
}
Run Code Online (Sandbox Code Playgroud)
这仍然有"命名空间问题"; 该struct名称(称为"结构标签")必须是唯一的,而不能声明嵌套结构,通过本身是有用的.它适用于收集功能,并且是您经常在C中看到的一种技术.
更新:以下是实施方面的外观,这是在评论中要求的:
#include "mycoolapi.h"
/* Note: This does **not** pollute the global namespace,
* since the function is static.
*/
static int add(int x, int y)
{
return x + y;
}
struct MyCoolApi * my_cool_api_initialize(void)
{
/* Since we don't need to do anything at initialize,
* just keep a const struct ready and return it.
*/
static const struct MyCoolApi the_api = {
add
};
return &the_api;
}
Run Code Online (Sandbox Code Playgroud)
小智 6
你被C++吓到了,这是一种耻辱,因为它有名称空间来处理这个问题.在C中,你几乎只限于使用前缀 - 你当然不能"在一个结构中放置api操作".
编辑:在回答关于允许用户指定自己的前缀的第二个问题时,我会像瘟疫一样避免它.99.9%的用户会对你提供的任何前缀感到满意(假设它不是太愚蠢),并且在他们必须跳过以满足剩余的0.1%的篮球(宏,结构,等等)时会非常不安.
作为库用户,您可以通过预处理器轻松定义自己的缩短名称空间;结果看起来有点奇怪,但它有效:
#define ns(NAME) my_cool_namespace_ ## NAME
Run Code Online (Sandbox Code Playgroud)
使得可以写
ns(foo)(42)
Run Code Online (Sandbox Code Playgroud)
代替
my_cool_namespace_foo(42)
Run Code Online (Sandbox Code Playgroud)
作为库作者,您可以提供此处所述的缩写名称。
如果您遵循unwinds 的建议并创建 API 结构,则应该将函数指针设为编译时常量以使 inlinig 成为可能,即在您的.h文件中使用以下代码:
// canonical name
extern int my_cool_api_add(int x, int y);
// API structure
struct my_cool_api
{
int (*add)(int x, int y);
};
typedef const struct my_cool_api *MyCoolApi;
// define in header to make inlining possible
static MyCoolApi my_cool_api_initialize(void)
{
static const struct my_cool_api the_api = { my_cool_api_add };
return &the_api;
}
Run Code Online (Sandbox Code Playgroud)