“#define”和“#define 1”的区别

4
在下面的例子中,1 看起来是不必要的(可能会引起误解),但我在多个检查 #ifdef 的情况下看到过这种写法:
#ifndef __NEWLIB_H__

#define __NEWLIB_H__ 1

使用上述方式与使用简单的#define __NEWLIB_H__之间是否有区别或原因?


6
这并没有回答问题,但是提到包含两个连续下划线(__NEWLIB_H__)和以下划线后跟大写字母开头的名称被保留供实现使用。不要在你的代码中使用它们。 - Pete Becker
1
@PeteBecker 是的,这段代码实际上是来自于实现。 - abc
1
@abc 为了明确起见,Pete 所指的“实现”是指 C++ 语言的实现。不是你的函数的实现(除非你正在编写标准库)。 - eerorika
2
@eerorika Newlib是嵌入式目标标准库的实现。该文件来自GNU Arm嵌入式工具链。 - abc
1
@abc 啊。那么确实允许,事实上有必要使用保留标识符 :) - eerorika
3个回答

4

1 代表真,所以你可以在 #if 测试中使用该宏。这通常对于头文件保护不是非常有用,但肯定不会有什么坏处。对于其他可能在布尔表达式中进行测试的宏,真值绝对是有用的。

有些人只是喜欢一致性。如果在命令行上输入 -D TESTME,那么这就是 gcc 默认选择的定义。

然而,

#define __NEWLIB_H__ 1

除非在标准库的实现中使用,否则不应该使用以两个下划线(或一个下划线和一个大写字母)开头的名称,因为这些名称被保留供实现使用,并且不应在便携式应用程序中使用。


2
好的,是的,评论区里有人发表了类似的评论,但在这种情况下,它实际上是标准库的一个实现。 - abc
1
能否说明一下-DTESTME的含义?令人惊讶的是,我在大约1000页的gcc文档或互联网上都找不到它的解释。 - abc
1
@abc:它的意思是“预定义宏TESTME”(在这种情况下为默认值,但通常提供显式值)。用于将配置设置传递到编译中。 (https://gcc.gnu.org/onlinedocs/gcc-9.3.0/gcc/Preprocessor-Options.html#Preprocessor-Options) - rici

3

当仅用作#include保护时,这两者没有区别。

#ifndef __NEWLIB_H__
#define __NEWLIB_H__

并且

#ifndef __NEWLIB_H__
#define __NEWLIB_H__ 1

然而,一般来说,有一个区别。

编译错误

#ifndef ABCD
#define ABCD
#endif

int main()
{
#if defined(ABCD) && (ABCD == 1)
   std::cout << "ABCD is 1\n";
#else
   std::cout << "ABCD is not 1\n";
#endif
}

输出字符串"ABCD is 1"

#ifndef ABCD
#define ABCD 1
#endif

int main()
{
#if defined(ABCD) && (ABCD == 1)
   std::cout << "ABCD is 1\n";
#else
   std::cout << "ABCD is not 1\n";
#endif
}

输出字符串"ABCD不是1"

#ifndef ABCD
#define ABCD 10
#endif

int main()
{
#if defined(ABCD) && (ABCD == 1)
   std::cout << "ABCD is 1\n";
#else
   std::cout << "ABCD is not 1\n";
#endif
}

2

#define 单独使用 会将该符号替换为空

另一方面,如你所说的,#define 1会在文件中出现的每一个位置都用1替换该符号。例如,以下代码:

#include <iostream>

#define EXAMPLE "hello"

int main()
{
    std::cout << EXAMPLE;

    return 0;
}

打印

hello

这是因为这里的EXAMPLE被替换成了"hello",使得打印语句等同于:
std::cout << "hello";

如果我们将#define语句改为以下内容:
#define EXAMPLE

这会导致编译错误

main.cpp: In function ‘int main()’:
main.cpp:15:25: error: expected primary-expression before ‘;’ token
     std::cout << EXAMPLE;

为什么会使用第二种形式的#define?这是因为还有另一种处理器指令可以使用,叫做#ifdef

#include <iostream>

#define EXAMPLE

int main()
{
#ifdef EXAMPLE
    std::cout << "EXAMPLE defined.";
#endif

    return 0;
}

这将打印:

EXAMPLE defined.

因为 #ifdef(以及它的相关指令 #ifndef)只需要定义符号,我们不需要真正给它一个值。它只需要存在就可以工作。
你经常会在头文件保护中看到这种东西(这可能是你正在看到的)。你也可以在平台识别或甚至用于确定编译器是否使用 C++ 中看到它。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接