#ifndef如何处理全局声明的变量和我自己的变量
How does the #ifndef deal with the globally declared variables and my own variables?
有一个问题让我很困惑。我知道这样做不对,但我不知道为什么。以及#ifndef#如何定义#endif。同谋者如何处理变量,如下面的"a"answers"b";
代码很简单:(myh.h(:
#ifndef P_H
#define P_H
struct P{
int a;
};
int b;
#endif
另一个文件s.cpp
#include"myh.h"
P a1;
主.cpp:
#include<iostream>
#include"myh.h"
using namespace std;
int main()
{
P a2;
return 0;
}
错误是b的多重定义;正如我所知。我有两个问题:1.正如一些书所说,如果你使用#ifndef,编译器不会包含两次,那么为什么"b"似乎包含两次。
- "a"、"b"answers"P"有什么区别。为什么"a"answers"P"毫无疑问。我不知道我认为"P"是一个与"b"水平相同的变量是否正确?或者"P"只是类型的一个定义
如果它是局部和全局的区别,为什么"p"是对的?
我真的很困惑。请原谅你帮我。谢谢。
首先,关于编译:
您必须了解编译器将首先单独编译每个cpp文件
(在链接过程中,它们在可执行文件中结合在一起之前(
如果您有一个文件main.cpp,其中有两次#include <abc.h>
,
您可以防止第二个include在#ifndef
-使用中出现错误
如果您有一个包含a.h
和b.h
的main.cpp,但a.h
也包含b.h
,
CCD_ 7等也会有所帮助。
但是:由于cpp文件(连同包含的头文件(是单独处理的,
如果在不同的cpp文件中包含相同的头文件,则没有帮助。
Ie。您可以随心所欲地包含标题,但它们不应该包含变量。
关于你的第二个问题:p只是一个"描述"什么是"p"。
(每个P都有一个int a
。但在那个时候,没有P。(。
b是一个实际的int,它可以容纳数字。。。
这是一个非常常见的问题-它可以在某些链接器(而不是编译器(上工作,但不能在其他链接器上工作(正如您所发现的(。
问题是int b是在标头中声明的,这意味着它在包括myh.h的每个文件中都被声明为全局可见。include保护程序将保护您在同一文件中不多次定义同一内容,但不会保护您在不同文件中不多次定义。
如何修复
- 不要这样做。如果int b不需要是全局的,则不要将其粘贴在标头中
- 在myh.h中,将其声明为extern int b。在main.cpp中,将其声明为int b这是一个常见的修复方法,但这意味着如果您更改b的类型,则需要在两个位置进行更改
-
稍微复杂一点。在我的中
#ifdef main_c #define EXTERN #else #define EXTERN extern #endif EXTERN int b;
在main.cpp 中
#define main_c #include "myh.h"
回答第二个问题,b是全局变量,p是局部变量。
标题保护分别适用于每个翻译单元。您至少有两个(s.cpp和main-cpp(。因此,"int b"是以这些翻译单位定义的。
还要注意,预处理器指令不会影响编译器,而是影响传递给编译器的经过预处理的文本。
将您的变量声明为extern int b
,并在(可能(s.cpp中包含int b
;
顺便说一句:p实际上是不同的变量。正如你所说,一个是奈恩的本地人,另一个是s.cpp的全球人。
这里有一些东西可以帮助您"发现"问题:
首先,错误不是编译时错误,而是链接时错误。尝试:编译s.cpp:
g++ -c s.cpp
这应该编译得很好。由于s.cpp具有#include "myh.h"
,因此b的定义将出现在s.o 中
编译main.cpp
g++ -c main.cpp
这也应该编译得很好。由于main.cpp有#include "myh.h"
,b的定义将出现在main.o中
现在尝试链接这两个.o文件。简单的方法是:
g++ s.o main.o
这应该会给你关于b的多重定义的错误。原因是符号b同时存在于s.o和main.o中。Linker给出了这个错误。
要查看对象文件中的所有符号,可以使用nm
命令。尝试:
nm s.o
也可以尝试:
nm main.o
两者都应包含一行:
00000000 B b
现在,为什么我们没有得到struct P
或int a
的错误?因为它们不是符号表的一部分。
- 在将变量声明为引用时,堆在释放后使用
- 静态变量声明和定义
- 在变量声明中使用 for 循环
- 向量索引变量声明(size_t 或 std::vector<DATATYPE>::size_type)
- C++ 类型类的变量声明不命名类型?
- 将本地 OpenCV Mat 变量声明为静态以防止重新分配
- std::enable_if 更改成员 *变量* 声明/类型
- 在C++中,变量声明左侧的大括号是什么意思?
- 将变量声明为全局变量,然后声明为局部变量 -Shadowing-
- 命名空间内C++变量声明
- 将静态全局变量声明为内联有什么意义吗?
- 如何将一个变量声明为另一个变量的值
- 如何将迭代器变量声明为私有成员变量
- 没有变量声明为函数,但错误:二进制表达式的操作数无效
- 有没有人有书面证据来保证函数中参数的定义方式与普通变量声明相同?
- ClangTool 如何获取变量声明中模板参数的位置?
- 标准与显式自动推导变量声明
- C 静态变量声明怪异链接器错误
- 如何为数组成员变量声明 getter/setter
- 可视C++变量声明