C++ 理解C++;汇编
我最近意识到,一般来说,我不知道c/c++编译器是如何工作的。我承认这最初是因为我试图理解头球后卫,但后来我意识到我缺乏编译的工作原理C++ 理解C++;汇编,c++,ide,header,compiler-errors,build-system,C++,Ide,Header,Compiler Errors,Build System,我最近意识到,一般来说,我不知道c/c++编译器是如何工作的。我承认这最初是因为我试图理解头球后卫,但后来我意识到我缺乏编译的工作原理 以Visual C++为例;有“头文件”文件夹、“资源文件”文件夹和“源文件”文件夹。分离这些文件夹和您在其中放置的内容有什么意义吗?对我来说,它们都是源文件。以代码片段为例: 片段1 及 及 及 //main.cpp #包括 #包括“a1.cpp” void main() { 库特 未编译头文件 #include指令直接粘贴可包含文件的内容,而不是#inclu
以Visual C++为例;有“头文件”文件夹、“资源文件”文件夹和“源文件”文件夹。分离这些文件夹和您在其中放置的内容有什么意义吗?对我来说,它们都是源文件。以代码片段为例:
片段1 及 及 及//main.cpp
#包括
#包括“a1.cpp”
void main()
{
库特
未编译头文件
#include指令直接粘贴可包含文件的内容,而不是#include行
所有源文件(main的redargless)都编译成.o或.obj文件
所有obj文件都与外部.lib文件(如果有)链接在一起
你会得到一个可执行文件
关于第2点:
example
//a.h
int
//b.h
x =
//c.h
5
//main.cpp
#include <iostream>
int main()
{
#include "a.h"
#include "b.h"
#include "c.h"
;
std::cout << x << std::endl; //prints 5 :)
}
示例
//a、 h
int
//b、 h
x=
//c、 h
5.
//main.cpp
#包括
int main()
{
#包括“a.h”
#包括“b.h”
#包括“c.h”
;
std::cout您的问题实际上不是关于编译器,而是关于IDE如何处理整个构建系统。大多数C/C++项目的构建系统分别编译每个.C
或.cpp
文件,然后将生成的对象文件链接到最终的可执行文件中。在您的情况下,IDE正在编译任何您在项目中拥有的文件扩展名为.cpp
,然后链接生成的对象。您看到的行为可以解释如下:
a1.cpp
缺少一个;
,因此当IDE尝试编译该文件时,您会收到关于“文件意外结束”的错误
b
未在main.cpp
编译单元中的任何位置声明,因此您会收到一个关于未定义标识符的错误
b
存在于main.cpp
和a1.cpp
编译单元中(显然是在a1.cpp
中,并通过将包含在main.cpp
中)。您的IDE编译这两个文件-现在a1.o
和main.o
每个文件都包含一个名为b
的对象。链接时,会出现重复符号错误
这里需要注意的一点是,IDE编译每个.cpp
文件,而不仅仅是main.cpp
及其包含的文件,然后链接生成的对象,这一点解释了您看到的所有行为
我建议用一个创建自己的MaFC++文件来设置命令行测试项目,它将教你所有的构建系统的内部工作,然后你可以将这些知识应用到IDE的内部工作。
< P>编译器从你告诉它的地方提取源文件。编译器需要做什么,不同的文件夹就在那里,因为IDE就是这样组织文件的
此外,代码段2中的错误来自链接器,而不是编译器。
编译器已将main.cpp和a1.cpp编译成目标文件main.obj和a1.obj,然后链接器正试图生成一个组合这些目标文件的可执行文件,但变量b同时位于a1.obj(直接)和main.obj(通过包含a1.cpp)中,因此您得到了“已定义”的错误。include语句将该文件插入到生成#include的文件中。因此,您的代码片段3 main.cpp在编译之前将变成以下内容
// main.cpp
// All sorts of stuff from iostream
//a1.cpp
int b = 4;
void main()
{
cout << b;
}
//main.cpp
//来自iostream的各种东西
//a1.cpp
int b=4;
void main()
{
您在案例1和案例3中看到的问题是VS特有的。VS显然试图编译main.cpp和a1.cpp
案例1:当VS试图编译a1.cpp时,它有一个语法错误(缺少分号),编译失败
案例2:您没有在main.cpp或任何包含的文件中声明变量b
。因此编译失败
案例3:这是一个链接器错误。由于include,在main.cpp和a1.cpp中都声明了int b
。因为它们都不是静态的或外部的,所以在同一范围内声明了两个具有相同标识符的全局变量。这是不允许的。您告诉构建系统要编译哪些文件。对于ViSUAL C++,它将自动编译任何添加到项目中的名为*.CPP的文件。虽然你可以进入项目设置并告诉它不要。
它不会编译名为*.h的文件(但如果您明确告诉它,它可以编译)
#include指令是编译器在进行任何编译之前处理的东西(称为预处理器)。它基本上会获取指向的文件,并在#include指令出现在文件中时将其粘贴到正在编译的源文件中。然后编译器将整个内容编译为一个完整的单元
因此,在您的示例中:
片段1
构建系统分别编译a1.cpp和main.cpp。因此,当它遇到错误om a1.cpp时,它会报告它
片段2
请注意,它单独编译这些文件,彼此不了解,因此当您在main.cpp中引用b时,它不知道a1.cpp中定义了b
片段3
现在你已经在main.cpp中包含了a1.cpp,所以它编译main.cpp,看到b的定义并说,好的,我在全局范围内有一个b。然后它编译a1.cpp,并说,好的,我在全局范围内有一个b
<>现在链接器在AN和A=中尝试把A1和Advin结合在一起,现在告诉你,嘿,我有2个B的ATE全局范围。没有好的。 < P>因为似乎有两种方式理解你的问题,我将回答C++的理解。
//main.cpp
#include <iostream>
#include "a1.h"
void main()
{
cout << r;
}
//a1.h
int r=4 //<--semicolon left out on purpose
//a1.cpp
int b = 4;
//main.cpp
#include <iostream>
void main()
{
cout << b;
}
//a1.h
int r=4 //<--semicolon left out on purpose
//a1.cpp
int b = 4;
//main.cpp
#include <iostream>
#include "a1.cpp"
void main()
{
cout << b;
}
example
//a.h
int
//b.h
x =
//c.h
5
//main.cpp
#include <iostream>
int main()
{
#include "a.h"
#include "b.h"
#include "c.h"
;
std::cout << x << std::endl; //prints 5 :)
}
// main.cpp
// All sorts of stuff from iostream
//a1.cpp
int b = 4;
void main()
{
cout << b;
}