在C中正确处理平台细节(unix/windows)?

dla*_*tte 2 c macros portability coding-style

这个问题是故意非常通用的,虽然我在这里和那里涉猎,但我并不是一个C程序员.以下代码故意模糊,可能无法编译,但我希望你明白......

处理平台细节似乎是动态的,像C这样的编译语言似乎是不必要甚至可怕的:

int main(int argc, char *argv[]) {
    if (windows)
        dowindowsroutine();
    else
        dounixroutine();
    return 0;
}
Run Code Online (Sandbox Code Playgroud)

但是,通过非常基本的宏来处理平台细节似乎也很粗糙,因为函数被切割成可能无法正确编译的小块(读取C#define宏的答案以用于类似问题的调试打印).

int main(int argc, char *argv[]) {
    #ifdef windows
    dowindowsroutine();
    #else
    dounixroutine();
    #endif
    return 0;
}
Run Code Online (Sandbox Code Playgroud)

那么这样做的"正确"方法是什么?这是个案的基础吗?有没有一种很好的方法可以完全保留这些粗糙的宏?我记得在某处(可能在内核文档或相关内容中)读取宏(更重要的是,复杂的宏逻辑)是针对头文件而不是.c文件.你怎么处理这种东西?

我厌倦了ifdef在函数内部的"意大利面条代码"...我觉得有些情况可能没问题,但我看到的大多数代码都滥用它.

注意:我已经看到一些perl XS代码看起来像包装函数原型和东西,但这是唯一的方法吗?在社区中有点不公平吗?或者那样好吗?来自perl,python,shell等主要是"脚本化"的背景......我很难说.

更新:让我更清楚一点,我试图避免的问题是我不想要乱码.我希望能够确保如果我的代码在linux的编译时断开,它也会在编译时在windows中中断.使用不稳定的代码,它可以打破编译窗口,但不是Linux,反之亦然.这种事可能吗?到目前为止最接近这一点的是ifdef整个函数,但是函数名是相同的,有一个更好的解决方案,有一个接口,但操作系统特定的部分有他们的操作系统名称嵌入名称?

Nik*_*sov 6

我认为处理这个问题的正确方法是将代码库拆分为特定于平台的模块,并在构建时将它们组合在一起(这当然需要某种平台抽象层.)这样,你的Unix代码就不会出现Windows调用,反之亦然.有效地将ifdef头痛转移到makefile.