C++ #ifndef 对于包含文件,为什么头文件全部大写?

发布于 2024-09-25 03:57:27 字数 177 浏览 3 评论 0原文

我想知道为什么 #ifndef 指令后面的名称总是全部大写并且似乎与实际头文件的名称不匹配?与此相关的规则是什么?我一直在网上查找,但没有找到任何解释。如果我的头文件名为 myheader.h 就可以使用:

#ifndef MYHEADER

如果可以,为什么?规则是什么?

I wonder why the name after the #ifndef directive is always all caps and don't seem to match the name of the actual header file? What are the rules surrounding this? I've been looking around the webs but, I haven't found any explanation for this. If my header file is called myheader.h would it then be ok to use:

#ifndef MYHEADER

If so, why? What are the rules?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(7

各空 2024-10-02 03:57:27

这些是预处理器符号,没有这样的规则。 (只要它们与标头中的#defines 匹配)

但是,约定是对预处理器符号使用全部大写。

These are preprocessor symbols and have no such rules. (as long as they match the #defines in the headers)

However, convention is to use all-caps for preprocessor symbols.

逆蝶 2024-10-02 03:57:27

没有“规则”,只有惯例。第一个也是最常用的约定是所有预编译器宏都是大写的,因此标头保护也应该是全大写的。

至于宏名称,我使用的(以及我见过的大多数代码使用的)只是标题的名称(如上所述,全部大写),包括扩展名,用下划线替换点,然后是_已包含

#ifndef MYHEADER_HPP_INCLUDED
#define MYHEADER_HPP_INCLUDED
// ...
#endif

请注意,许多人在此类标识符前面加上下划线或双下划线,但这不是一个好的做法,因为标准指定以双下划线开头(或包含)的标识符以及以单下划线开头后跟大写字母的标识符保留给编译器/所有范围内特定于库的内容(例如 VC++ 中的 __declspec 或标准头文件中使用的宏);所有其他以下划线开头的标识符都保留在全局范围内。因此不应使用此类标识符来避免冲突。

有关此内容的更多信息此处。

There's no "rule", there are just conventions. The first and most used convention is that all precompiler macros are all uppercase, so header guards too should be all uppercase.

As for the macro name, what I use (and what most of the code I've seen uses) is just the name of the header (as said, turned to all uppercase) including extension, replacing the dot with an underscore, followed by _INCLUDED.

#ifndef MYHEADER_HPP_INCLUDED
#define MYHEADER_HPP_INCLUDED
// ...
#endif

Note that many prepend such identifiers with an underscore or a double underscore, but it's not good practice, since the standard specifies that identifiers beginning (or containing) double underscores and those beginning with a single underscore followed by an uppercase letter are reserved for compiler/library-specific stuff (e.g. __declspec in VC++ or macros used in the standard headers) at all scopes; all the other identifiers beginning with a single underscore are reserved at the global scope. So such identifiers shouldn't be used to avoid collisions.

More info on this stuff here.

阿楠 2024-10-02 03:57:27

不需要全部大写。这只是共同约定。我通常使用类似 #ifndef MYHEADER_H_INCLUDED 的内容。

It's not required to be all caps. It's just the common convention. I usually use something like #ifndef MYHEADER_H_INCLUDED.

别在捏我脸啦 2024-10-02 03:57:27

Google 包含防护找出事情的真正含义。

关于全部大写:宏的约定全部大写。原因是宏是由预处理器处理的,预处理器是一种神秘的文本处理工具,它对 C++ 一无所知,并且最好将公共标识符排除在外,以免它践踏它们,造成大混乱。

Google for "include guard" to find what the thing is actually about.

About the all-caps: It's a convention for macros to be in all-upper-case. The reason is that macros are processed by the preprocessor, an arcane text processing tool, that knows nothing of C++, and is best shut out of common identifiers, lest it tramples all over them, creating a big mess.

只怪假的太真实 2024-10-02 03:57:27

这个想法是确保你的头文件在构建过程中只被读取一次。实现这一点的习惯用法是结构:

   #ifndef _SOME_UNIQUE_NAME
   #define _SOME_UNIQUE_NAME
   /* The actual header code */
   #endif

这意味着您应该选择一个您确信是唯一的并且是 #ifndef 的有效标识符的名称。您还应该确保标识符没有在实际代码中使用或与变量或其他东西混淆。使用大写标签可以清楚地标记该习语。除此之外,决定这种选择的只是惯例而不是语言。 Visual Studio 的向导会生成类似 GUID 的标识符。一些编译器支持 #pragma Once 具有相同的效果。

The idea is to make sure your header file is only read once during build. The idiom to accomplish that is the structure:

   #ifndef _SOME_UNIQUE_NAME
   #define _SOME_UNIQUE_NAME
   /* The actual header code */
   #endif

This means that you should choose a name that you are pretty sure will be unique and is a valid identifier for #ifndef. You should also make sure that the identifier is not used in actual code or confused with a variable or something. Having an upper case tag marks the idiom clearly. Besides that, it is merely conventions not language that dictate that choice. Visual Studio's wizards generates a GUID like identifier for. Sone compilers support #pragma once that have the same effect.

要走就滚别墨迹 2024-10-02 03:57:27

它完全是主观的,除了通常与命名预处理器宏的字符集相关的规则之外,没有强制规则。宏通常以大写形式定义。这往往有助于它们在源代码中脱颖而出。我倾向于坚持的一个约定是文件名的严格大写版本,其中句点替换为下划线以及前导和尾随下划线。因此,对于名为 DataTableNameMangler.hpp 的文件,包含保护将如下所示:

#ifndef _DATATABLENAMEMANGLER_HPP_
#define _DATATABLENAMEMANGLER_HPP_

...

#endif // _DATATABLENAMEMANGLER_HPP_

虽然我强烈建议名称与文件名完全匹配,但为了保持一致性,这没有什么充分的理由。我通常使用一个小的类创建器脚本来生成我的初始类。下面的 Bash 片段给出了一个想法:

#!/bin/bash
INC_GUARD_NAME="_${1^^*}_HPP_"
echo "#ifndef $INC_GUARD_NAME"
echo "#ifndef $INC_GUARD_NAME"
echo
echo "class $1 {};"
echo
echo "#endif // $INC_GUARD_NAME"

因此:

$ ./makeclass.bash DataTableNameMangler
#ifndef _DATATABLENAMEMANGLER_HPP_
#ifndef _DATATABLENAMEMANGLER_HPP_

class DataTableNameMangler {};

#endif // _DATATABLENAMEMANGLER_HPP_

这自然只是一个非常基本的示例。重要的是,请记住将注释放在最后一行的守卫名称之前。 #endif 不带任何参数,因此宏将被传递给 C++ 编译器,如果没有注释,C++ 编译器将会抱怨它。

It's completely subjective and there are no enforced rules other than those normally associated with the character set for naming pre-processor macros. It's conventional for macros to be defined in upper case. This tends to help them stand out in source code. A convention I tend to stick to is the strict capitalised version of the filename with the period replaced by an underscore and leading and trailing underscores. So, for a file called DataTableNameMangler.hpp the include guard would look like:

#ifndef _DATATABLENAMEMANGLER_HPP_
#define _DATATABLENAMEMANGLER_HPP_

...

#endif // _DATATABLENAMEMANGLER_HPP_

There's no great reason for this though I strongly recommend for consistency that the name matches the filename exactly. I normally use a little class creator script to generate my initial classes. The following Bash snippet gives an idea:

#!/bin/bash
INC_GUARD_NAME="_${1^^*}_HPP_"
echo "#ifndef $INC_GUARD_NAME"
echo "#ifndef $INC_GUARD_NAME"
echo
echo "class $1 {};"
echo
echo "#endif // $INC_GUARD_NAME"

Thus:

$ ./makeclass.bash DataTableNameMangler
#ifndef _DATATABLENAMEMANGLER_HPP_
#ifndef _DATATABLENAMEMANGLER_HPP_

class DataTableNameMangler {};

#endif // _DATATABLENAMEMANGLER_HPP_

This is naturally just a very basic example. Importantly, remember to put the comment before the guard name on the last line. #endif takes no parameters so the macro will be passed on to the C++ compiler which will complain about it if it's not commented.

我也只是我 2024-10-02 03:57:27

您可以使用任何您想要的名称,但您希望使其唯一,以便该值不会在标头之外定义,因此使用大写的标头名称只是确保这一点的一个很好的约定。

You can use any name you want, but you want to make it unique so that value won't be defined outside your header by any chance, so using header name with uppercase is just a nice convention to ensure that.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文