将值设置为“const char *”是否合适?在头文件中

发布于 2024-09-02 07:46:34 字数 554 浏览 12 评论 0原文

我见过人们使用两种方法来声明和定义 char *

Medhod 1:头文件有以下

extern const char* COUNTRY_NAME_USA = "USA";

Medhod 2:
头文件具有以下声明:

extern const char* COUNTRY_NAME_USA;

cpp 文件具有以下定义:

extern const char* COUNTRY_NAME_USA = "USA";
  1. 方法 1 在某些方面是否错误?
  2. 两者有什么区别?
  3. 我理解 "const char * const var" 和 "const char * var" 之间的区别。如果在上述方法中,如果像方法 1 那样在标头中声明并定义了“const char * const var”,那么这是否有意义?

I have seen people using 2 methods to declare and define char *.

Medhod 1: The header file has the below

extern const char* COUNTRY_NAME_USA = "USA";

Medhod 2:
The header file has the below declaration:

extern const char* COUNTRY_NAME_USA;

The cpp file has the below definition:

extern const char* COUNTRY_NAME_USA = "USA";
  1. Is method 1 wrong in some way ?
  2. What is the difference between the two ?
  3. I understand the difference between "const char * const var" , and "const char * var". If in the above methods if a "const char * const var" is declared and defined in the header as in method 1 will it make sense ?

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

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

发布评论

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

评论(3

酷炫老祖宗 2024-09-09 07:46:34

第一种方法确实是错误的,因为它在头文件中使用外部链接对对象COUNTRY_NAME_USA进行了定义。一旦该头文件被包含到多个翻译单元中,就会违反单一定义规则 (ODR)。该代码将无法编译(更准确地说,它将无法链接)。

第二种方法是正确的。不过,关键字 extern 在定义中是可选的,即在 cpp 文件中,您可以

const char* COUNTRY_NAME_USA = "USA"

假设头文件中的声明在此翻译单元中的定义之前。

另外,我猜由于对象名称是大写的,因此它可能是一个常量。如果是这样,则应将其声明/定义为 const char* const COUNTRY_NAME_USA (注意额外的 const)。

最后,考虑到最后一个细节,您可以像

const char* const COUNTRY_NAME_USA = "USA"; // no `extern`!

在头文件中一样定义常量。由于它现在是一个常量,因此默认情况下具有内部链接,这意味着即使头文件包含在多个翻译单元中,也不会发生 ODR 冲突。在这种情况下,您会在每个翻译单元中获得一个单独的 COUNTRY_NAME_USA 左值(而在 extern 方法中,您会为整个程序获得一个左值)。只有您知道您的情况需要什么。

The first method is indeed wrong, since it makes a definition of an object COUNTRY_NAME_USA with external linkage in the header file. Once that header file gets included into more than one translation unit, the One Definition Rule (ODR) gets violated. The code will fail to compile (more precisely, it will fail to link).

The second method is the correct one. The keyword extern is optional in the definition though, i.e. in the cpp file you can just do

const char* COUNTRY_NAME_USA = "USA"

assuming the declaration from the header file precedes this definition in this translation unit.

Also, I'd guess that since the object name is capitalized, it is probably intended to be a constant. If so, then it should be declared/defined as const char* const COUNTRY_NAME_USA (note the extra const).

Finally, taking that last detail into account, you can just define your constant as

const char* const COUNTRY_NAME_USA = "USA"; // no `extern`!

in the header file. Since it is a constant now, it has internal linkage by default, meaning that there is no ODR violation even if the header file is included into several translation units. In this case you get a separate COUNTRY_NAME_USA lvalue in each translation unit (while in extern method you get one for the entire program). Only you know what you need in your case .

别闹i 2024-09-09 07:46:34

有什么意义?

如果您想查找字符串(可以本地化),这将是最好的:

namespace CountryNames {
    const char* const US = "USA";
};

由于指针是 const,它现在具有内部链接并且不会导致多个定义。大多数链接器还会组合冗余常量,因此您不会浪费可执行文件中的空间。

如果您想通过指针相等性来比较字符串,则上述内容不可移植,因为仅当链接器执行常量折叠优化时指针才会相等。在这种情况下,在头文件中声明一个 extern 指针是可行的方法(如果您不打算重新定位它,它也应该是 const )。

What's the point?

If you want to lookup strings (that could be localized), this would be best:

namespace CountryNames {
    const char* const US = "USA";
};

Since the pointer is const, it now has internal linkage and won't cause multiple definitions. Most linkers will also combine redundant constants, so you won't waste space in the executable.

If you want to compare strings by pointer equality though, the above isn't portable because the pointers will only be equal if the linker performs the constant-folding optimization. In that case declaring an extern pointer in the header file is the way to go (and it again should be const if you don't intend to retarget it).

绅士风度i 2024-09-09 07:46:34

如果必须有全局变量,通常的做法是在 .h 文件中声明它们并在一个(且仅有一个).cpp 文件中定义它们。

在 .h 文件中;

extern int x;

在 .cpp 文件中;

int x=3;

我在您的示例中使用了 int (也许是最基本的基本类型?)而不是 const char * ,因为问题的本质并不取决于变量的类型。

基本思想是您可以多次声明一个变量,因此包含 .h 文件的每个 .cpp 文件都声明该变量,这很好。但你只定义一次。定义是为变量分配初始值的语句(使用=)。您不需要 .h 文件中的定义,因为如果 .h 文件包含在多个 .cpp 文件中,您将获得多个定义。如果一个变量有多个定义,则在链接时会出现问题,因为链接器想要分配该变量的地址,但如果有该变量的多个副本,则无法合理地执行此操作。

稍后添加其他信息,以尝试缓解 Sud 的困惑;

尝试将您的问题减少到最少的部分,以便更好地理解它;

假设您有一个包含三个 .cpp 文件的程序。为了构建程序,单独编译每个 .cpp 以创建三个目标文件,然后将这三个目标文件链接在一起。如果三个.cpp文件如下(示例A,组织良好);

file1.cpp

extern int x;

file2.cpp

extern int x;

file3.cpp

extern int x;

然后这些文件将毫无问题地编译并链接在一起(至少就变量 x 而言)。没有问题,因为每个文件只声明变量x。声明只是声明某个地方有一个我可能(或可能不)使用的变量。

实现相同目标的更好方法如下(示例 A,更好的组织);

header.h

extern int x;

file1.cpp

#include "header.h"

file2.cpp

#include "header.h"

file3.cpp

#include "header.h"

这实际上是完全相同的,对于三个编译中的每一个,编译器在处理 .cpp 文件(或专家称之为翻译单元)时都会看到与之前相同的文本,因为 #include 指令只是从另一个文件中提取文本。尽管如此,这还是对前面示例的改进,因为我们只将声明放在一个文件中,而不是在多个文件中。

现在考虑另一个工作示例(示例 B,良好的组织);

file1.cpp

extern int x;

file2.cpp

extern int x;

file3.cpp

extern int x;
int x=3;

这也可以正常工作。所有三个 .cpp 文件均声明 x,其中一个文件实际定义它。我们可以继续在操作变量 x 的三个文件中的任何一个的函数中添加更多代码,并且我们不会收到任何错误。同样,我们应该使用头文件,以便声明仅进入一个物理文件(示例 B,更好的组织)。

header.h

extern int x;

file1.cpp

#include "header.h"

file2.cpp

#include "header.h"

file3.cpp

#include "header.h"
int x=3;

最后考虑一个不起作用的示例(示例 C,不起作用);

file1.cpp

int x=3;

file2.cpp

int x=3;

file3.cpp

int x=3;

每个文件都可以毫无问题地编译。问题发生在链接时,因为现在我们定义了三个单独的 int x 变量。它们具有相同的名称并且全局可见。链接器的工作是将单个程序所需的所有对象拉入一个可执行文件中。全局可见的对象必须具有唯一的名称,以便链接器可以将对象的单个副本放置在可执行文件中的一个定义的地址(位置),并允许所有其他对象在该地址访问它。在这种情况下,链接器无法使用全局变量 x 完成其工作,因此会产生错误。

顺便说一句,给出不同的定义不同的初始值并不能解决问题。在每个定义前面加上关键字 static 确实解决了这个问题,因为现在变量不是全局可见的,而是在定义它们的 .cpp 文件中可见。

如果将全局变量定义放入头文件中,则没有任何本质变化(示例 C,标头组织在这种情况下没有帮助);

header.h

int x=3;  // Don't put this in a .h file, causes multiple definition link error

file1.cpp

#include "header.h"

file2.cpp

#include "header.h"

file3.cpp

#include "header.h"

唷,我希望有人读到这篇文章并从中受益。有时,提问者迫切需要一个基本概念的简单解释,而不是高级计算机科学家的解释。

If you must have global variables, normal practice is to declare them in a .h file and define them in one (and only one) .cpp file.

In a .h file;

extern int x;

In a .cpp file;

int x=3;

I have used int (the most fundamental basic type perhaps?) rather than const char * as in your example because the essence of your problem doesn't depend on the type of variable.

The basic idea is that you can declare a variable multiple times, so each .cpp file that includes the .h file declares the variable, and that is fine. But you only define it once. The definition is the statement where you assign the variables initial value, (with an =). You don't want definitions in .h files, because then if the .h file is included by multiple .cpp files, you'll get multiple definitions. If you have multiple definitions of one variable, there is a problem at link time because the linker wants to assign the address of the variable and cannot reasonably do that if there are multiple copies of it.

Additional information added later to try and ease Sud's confusion;

Try to reduce your problem to it's minimal parts to understand it better;

Imagine you have a program that comprises three .cpp files. To build the program each .cpp is compiled separately to create three object files, then the three object files are linked together. If the three .cpp files are as follows (example A, good organization);

file1.cpp

extern int x;

file2.cpp

extern int x;

file3.cpp

extern int x;

Then the files will compile and link together without problem (at least as far as the variable x is concerned). There is no problem because each file is only declaring variable x. A declaration is simply stating that there is a variable out there somewhere that I may (or may not) use.

A better way of achieving the same thing is the following (example A, better organization);

header.h

extern int x;

file1.cpp

#include "header.h"

file2.cpp

#include "header.h"

file3.cpp

#include "header.h"

This is effectively exactly the same, for each of the three compilations the compiler sees the same text as earlier as it processes the .cpp file (or translation unit as the experts call it), because the #include directive simply pulls text from another file. Nevertheless this is an improvement on the earlier example simply because we only have our declaration in one file, not in multiple files.

Now consider another working example (example B, good organization);

file1.cpp

extern int x;

file2.cpp

extern int x;

file3.cpp

extern int x;
int x=3;

This will work fine as well. All three .cpp files declare x and one actually defines it. We could go ahead and add more code within functions in any of the three files that manipulates variable x and we wouldn't get any errors. Again we should use a header file so that the declaration only goes into one physical file (example B, better organization).

header.h

extern int x;

file1.cpp

#include "header.h"

file2.cpp

#include "header.h"

file3.cpp

#include "header.h"
int x=3;

Finally consider an example that just wouldn't work (example C, doesn't work);

file1.cpp

int x=3;

file2.cpp

int x=3;

file3.cpp

int x=3;

Each file would compile without problems. The problem occurs at link time because now we have defined three separate int x variables. The have the same name and are all globally visible. The linker's job is to pull all the objects required for a single program into one executable. Globally visible objects must have a unique name, so that the linker can put a single copy of the object at one defined address (place) in the executable and allow all the other objects to access it at that address. The linker cannot do it's job with global variable x in this case and so will choke out an error instead.

As an aside giving the different definitions different initial values doesn't address the problem. Preceding each definition with the keyword static does address the problem because now the variables are not globally visible, but rather visible within the .cpp file that the are defined in.

If you put a global variable definition into a header file, nothing essential has changed (example C, header organization not helpful in this case);

header.h

int x=3;  // Don't put this in a .h file, causes multiple definition link error

file1.cpp

#include "header.h"

file2.cpp

#include "header.h"

file3.cpp

#include "header.h"

Phew, I hope someone reads this and gets some benefit from it. Sometimes the questioner is crying out for a simple explanation in terms of basic concepts not an advanced computer scientist's explanation.

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