- mongodb - 在 MongoDB mapreduce 中,如何展平值对象?
- javascript - 对象传播与 Object.assign
- html - 输入类型 ="submit"Vs 按钮标签它们可以互换吗?
- sql - 使用 MongoDB 而不是 MS SQL Server 的优缺点
我必须使用大量的#ifdef i386 和 x86_64 用于特定于体系结构的代码,有时需要使用#ifdef MAC 或#ifdef WIN32... 等等特定于平台的代码代码。
我们必须保持通用代码库和可移植性。
但我们必须遵循#ifdef 的使用是严格不使用的准则。我不明白为什么?
作为这个问题的延伸,我还想了解何时使用 #ifdef ?
例如,dlopen() 在从 64 位进程运行时无法打开 32 位二进制文件,反之亦然。因此它的架构更具体。我们可以在这种情况下使用#ifdef 吗?
最佳答案
使用 #ifdef
代替编写可移植代码,您仍在编写多段特定于平台的代码。不幸的是,在许多(大多数?)情况下,您很快就会得到一个几乎难以理解的可移植代码和特定于平台的代码的混合体。
您还经常将 #ifdef
用于可移植性以外的目的(定义要生成的代码的“版本”,例如将包含什么级别的 self 诊断)。不幸的是,两者经常互动,并交织在一起。例如,将一些代码移植到 MacOS 的人认为它需要更好的错误报告,他补充道——但使其特定于 MacOS。后来,其他人认为更好的错误报告在 Windows 上会非常有用,所以他通过自动 #define
ing MACOS 如果定义了 WIN32 来启用该代码 - 但随后添加“只是多一些” #ifdef WIN32
在定义 Win32 时排除一些真正是 MacOS 特定的代码。当然,我们还添加了 MacOS 基于 BSD Unix 的事实,所以当 MACOS 被定义时,它也会自动定义 BSD_44 —— 但是(再次)转过身来排除一些 BSD 的“东西” "为 MacOS 编译时。
这很快就会退化为如下示例的代码(取自 #ifdef Considered Harmful):
#ifdef SYSLOG
#ifdef BSD_42
openlog("nntpxfer", LOG_PID);
#else
openlog("nntpxfer", LOG_PID, SYSLOG);
#endif
#endif
#ifdef DBM
if (dbminit(HISTORY_FILE) < 0)
{
#ifdef SYSLOG
syslog(LOG_ERR,"couldn’t open history file: %m");
#else
perror("nntpxfer: couldn’t open history file");
#endif
exit(1);
}
#endif
#ifdef NDBM
if ((db = dbm_open(HISTORY_FILE, O_RDONLY, 0)) == NULL)
{
#ifdef SYSLOG
syslog(LOG_ERR,"couldn’t open history file: %m");
#else
perror("nntpxfer: couldn’t open history file");
#endif
exit(1);
}
#endif
if ((server = get_tcp_conn(argv[1],"nntp")) < 0)
{
#ifdef SYSLOG
syslog(LOG_ERR,"could not open socket: %m");
#else
perror("nntpxfer: could not open socket");
#endif
exit(1);
}
if ((rd_fp = fdopen(server,"r")) == (FILE *) 0){
#ifdef SYSLOG
syslog(LOG_ERR,"could not fdopen socket: %m");
#else
perror("nntpxfer: could not fdopen socket");
#endif
exit(1);
}
#ifdef SYSLOG
syslog(LOG_DEBUG,"connected to nntp server at %s", argv[1]);
#endif
#ifdef DEBUG
printf("connected to nntp server at %s\n", argv[1]);
#endif
/*
* ok, at this point we’re connected to the nntp daemon
* at the distant host.
*/
这是一个相当小的例子,只涉及几个宏,但阅读代码已经很痛苦了。我个人看到(并且不得不处理)在实际代码中很多更糟。这里的代码很难看而且读起来很痛苦,但是仍然很容易弄清楚在什么情况下将使用哪些代码。在许多情况下,您最终会得到更复杂的结构。
为了给出一个具体的例子来说明我希望如何写,我会做这样的事情:
if (!open_history(HISTORY_FILE)) {
logerr(LOG_ERR, "couldn't open history file");
exit(1);
}
if ((server = get_nntp_connection(server)) == NULL) {
logerr(LOG_ERR, "couldn't open socket");
exit(1);
}
logerr(LOG_DEBUG, "connected to server %s", argv[1]);
在这种情况下,可能我们对 loggerr 的定义将是一个宏而不是一个实际的函数。这可能是微不足道的,所以有一个像这样的标题是有意义的:
#ifdef SYSLOG
#define logerr(level, msg, ...) /* ... */
#else
enum {LOG_DEBUG, LOG_ERR};
#define logerr(level, msg, ...) /* ... */
#endif
[暂时,假设预处理器可以/将处理可变参数宏]
考虑到你的主管的态度,即使这样可能也是 Not Acceptable 。如果是这样,那很好。取而代之的是宏,而是在函数中实现该功能。将函数的每个实现隔离在其自己的源文件中,并构建适合目标的文件。如果您有很多特定于平台的代码,您通常希望将其隔离到自己的目录中,很可能使用自己的 makefile1,并拥有一个顶级的 makefile 来选择哪个基于指定目标调用的其他 makefile。
关于c++ - 在代码中使用#ifdef 是一种不好的做法吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/8010234/
如果您想分享更多信息,可以在这里找到整个资源 指针: https://github.com/sergiotapia/DreamInCode.Net 基本上,我的API将为其他开发人员提供
关闭。这个问题需要更多focused .它目前不接受答案。 想改进这个问题吗? 更新问题,使其只关注一个问题 editing this post . 关闭 5 年前。 Improve this qu
我不是 SCM 工具的经验丰富的用户,尽管我确信它们的用处,当然。 我在以前的工作中使用了一些不起眼的商业工具,在当前的工作中使用了 Perforce,并在我的小型个人项目中使用了 TortoiseS
所以我想知道一些我应该避免在 javascript 中做的事情以获得良好的 SEO 排名。在我的下一个站点中,我将广泛使用 jquery 和 javascript,但不想牺牲 SEO。那么您认为我应该
基本上,我想知道什么是避免 future CSS 代码出现问题和混淆的最佳方法... 像这样命名 CSS 属性: div#content ul#navigation div.float-left (真
我是一名优秀的程序员,十分优秀!