I'm a C++ beginner and I'm studying the basics of the language. There is a topic in my book about the compiler and my problem is that I can not understand what the text wants to say:
我是一名C ++初学者,我正在研究该语言的基础知识。我的书中有一个关于编译器的主题,我的问题是我无法理解文本想要说的内容:
C++ is a compiled language so you need to translate the source code in a file that the computer can execute. This file is generated by the compiler and is called the object code ( .obj ), but a program like the "hello world" program is composed by a part that we wrote and a part of the C++ library. The linker links these two parts of a program and produces an executable file ( .exe ).
C ++是一种编译语言,因此您需要将源代码转换为计算机可以执行的文件。该文件由编译器生成,称为目标代码(.obj),但像“hello world”程序这样的程序由我们编写的部分和C ++库的一部分组成。链接器链接程序的这两部分并生成可执行文件(.exe)。
Why does my book tell that the file that is executed by the computer is the one with the obj suffix (the object code) and then say that it is the one with the exe suffix?
为什么我的书告诉计算机执行的文件是带有obj后缀的文件(目标代码),然后说它是带有exe后缀的文件?
4 个解决方案
#1
34
Object files are source compiled into binary machine language, but they contain unresolved external references (such as printf
,for instance). They may need to be linked against other object files, third party libraries and almost always against C/C++ runtime library.
目标文件是源代码编译成二进制机器语言,但它们包含未解析的外部引用(例如printf)。它们可能需要与其他目标文件,第三方库以及几乎总是针对C / C ++运行时库链接。
In Unix, both object and exe files are the same COFF format. The only difference is that object files have unresolved external references, while a.out files don't.
在Unix中,object和exe文件都是相同的COFF格式。唯一的区别是对象文件具有未解析的外部引用,而a.out文件则没有。
#2
10
The C++ specification is a technical document in English. For C++11 have a look inside n3337 (or spend a lot of money to buy the paperback ISO standard). In theory you don't need a computer to run a C++ program (you could use a bunch of human slaves, but that would be unethical, inefficient, and unreliable).
C ++规范是英文的技术文档。对于C ++ 11,请查看n3337内部(或花费大量资金购买平装ISO标准)。从理论上讲,你不需要一台计算机来运行一个C ++程序(你可以使用一堆人类奴隶,但那是不道德的,低效的,不可靠的)。
You could have a C++ implementation which is an interpreter, not a compiler (e.g. Ch by SoftIntegration)
你可以有一个C ++实现,它是一个解释器,而不是一个编译器(例如Ch by SoftIntegration)
If you install Linux on your laptop (which I recommend doing to every student) then you could have several free software C++ compilers, in particular GCC and Clang/LLVM (using g++
and clang
commands respectively). Source files are suffixed .cc
, or .cxx
, or .cpp
, or even .C
(I prefer .cc
), and you could ask the compiler to handle a file of some other suffix as a C++ source file (but that is not conventional). Then, both object files (suffixed .o
) and executables share the same ELF format. Conventionally, executables don't have any suffix (e.g. g++
is a binary executable, not doing much except starting other processes like cc1plus
-the compiler proper-, as
-the assembler-, ld
-the linker- etc...)
如果你在笔记本电脑上安装Linux(我建议你对每个学生都这样做)那么你可以有几个免费软件C ++编译器,特别是GCC和Clang / LLVM(分别使用g ++和clang命令)。源文件后缀.cc,或.cxx,或.cpp,甚至.C(我更喜欢.cc),你可以要求编译器处理一些其他后缀的文件作为C ++源文件(但不是常规)。然后,两个目标文件(后缀.o)和可执行文件共享相同的ELF格式。传统上,可执行文件没有任何后缀(例如,g ++是一个二进制可执行文件,除了启动其他进程,如cc1plus - 编译器本身,作为汇编程序,ld-链接器等等)没有做太多工作。
In all cases I strongly recommend:
在所有情况下,我强烈建议:
- to enable all warnings and debug info during compilation (e.g. use
g++ -Wall -g
....) - to improve your source code till you got no warnings
- to learn how to use the debugger (
gdb
) - to be able to build your program on the command line
- to use a version control system like git
- to use a good editor like
emacs
,gedit
,geany
, orgvim
- once you are writing programs in several source files, learn how to use a builder like
make
- to learn C++11 (or even perhaps C++14) rather than older C++ standards
- to also learn other programming languages (Ocaml, Scheme, Haskell, Prolog, Scala, ....) since they would improve your thinking and your way of coding in C++
- to study the source code of several free software coded in C++
- to read the documentation of every function that you are using, e.g. on cppreference or in man pages (for Linux)
- to understand what is undefined behavior (the fact that your program sometimes work does not make it correct).
在编译期间启用所有警告和调试信息(例如使用g ++ -Wall -g ....)
改进你的源代码,直到你没有警告
学习如何使用调试器(gdb)
能够在命令行上构建程序
使用像git这样的版本控制系统
使用像emacs,gedit,geany或gvim这样的好编辑器
一旦你在几个源文件中编写程序,学习如何使用像make这样的构建器
学习C ++ 11(甚至可能是C ++ 14)而不是旧的C ++标准
也学习其他编程语言(Ocaml,Scheme,Haskell,Prolog,Scala,....),因为它们可以改善你的思维和你在C ++中的编码方式
研究用C ++编写的几个*软件的源代码
阅读您正在使用的每个功能的文档,例如在cppreference或手册页(适用于Linux)
了解什么是未定义的行为(您的程序有时工作的事实并不能使其正确)。
Concretely, on Linux you could edit your Hello World program (file hello.cc
) with gedit
or emacs
(with a command like gedit hello.cc
) etc..., compile it using g++ -Wall -g hello.cc -o hello
command, debug it using gdb ./hello
, and repeat (don't forget to use git
commands for version control).
具体来说,在Linux上,您可以使用gedit或emacs(使用gedit hello.cc等命令)编辑Hello World程序(文件hello.cc)等等,使用g ++ -Wall -g hello.cc -o hello编译它命令,使用gdb ./hello调试它,然后重复(不要忘记使用git命令进行版本控制)。
Sometimes it makes sense to generate some C++ code, e.g. by some shell, Python, or awk
script (or even by your own program coded in C++ which generates C++ code!).
有时生成一些C ++代码是有意义的,例如通过一些shell,Python或awk脚本(甚至是你自己用C ++编写的程序,生成C ++代码!)。
Also, understand that an IDE is not a compiler (but runs the compiler for you).
另外,要了解IDE不是编译器(但为您运行编译器)。
#3
4
The languages used for programming computers along with the various software development tools have evolved over the years.
多年来,用于编程计算机的语言以及各种软件开发工具已经发生了变化。
The first computers were programmed with numbers entered by switches on a console.
第一台计算机使用控制台上的开关输入的数字进行编程。
Then people started developing languages and software that could be used to create software more easily and quicker. The first major development was creating assembler language where each line of source was converted by a computer program into a machine code instruction. Along with this came the development of linkers (which link pieces of machine code together into larger pieces). Assemblers were improved by adding a macro or preprocessor facility somewhat like the C/C++ Preprocessor though designed for assembly language.
然后人们开始开发可以更容易,更快速地创建软件的语言和软件。第一个主要的开发是创建汇编语言,其中每行源由计算机程序转换为机器代码指令。随之而来的是连接器的开发(将机器代码片段连接成更大的片段)。通过添加宏或预处理器工具来改进汇编程序,有点像C / C ++预处理器,虽然是为汇编语言设计的。
Then people created programming languages that looked more like people written languages rather than assembler (FORTRAN and COBOL and ALGOL for instance). These languages were easier to read and a single line of source might be converted into several machine instructions so it was more productive to write computer programs in these languages rather than assembler.
然后人们创建的编程语言看起来更像是人们编写的语言而不是汇编程序(例如FORTRAN和COBOL和ALGOL)。这些语言更易于阅读,并且可以将单行源转换为多个机器指令,因此以这些语言而不是汇编程序编写计算机程序会更高效。
The C programming language was a later refinement using lessons learned from the early programming languages such as FORTRAN. And C used some of the same software development tools that already existed such as linkers which already existed. Still later C++ was invented, starting off as a refinement of C introducing object oriented facilities. In fact the first C++ compiler was really a C++ translator which translated C++ source code to C source code which was then compiled with a C compiler. However modern C++ is compiled straight to machine code in order to provide the full functionality of the C++ standard with templates, lambdas, and all the other things with C++11 and later.
C编程语言是后来的改进,使用了早期编程语言(如FORTRAN)的经验教训。 C使用了一些已经存在的相同软件开发工具,例如已经存在的链接器。后来发明了C ++,开始是对C引入面向对象设施的改进。事实上,第一个C ++编译器实际上是一个C ++转换器,它将C ++源代码翻译成C源代码,然后用C编译器编译。然而,现代C ++直接编译为机器代码,以便使用C ++ 11及更高版本的模板,lambdas和所有其他东西提供C ++标准的全部功能。
The basic steps for creating an application from a C or C++ source file are as follows: (1) the source files are created, (2) the source files are compiled (which is really two steps, Preprocessor and compilation), (3) the object files that are created by the C/C++ compiler are linked to create the .exe
从C或C ++源文件创建应用程序的基本步骤如下:(1)创建源文件,(2)编译源文件(实际上是两个步骤,预处理器和编译),(3)由C / C ++编译器创建的目标文件被链接以创建.exe
So you have these steps of transforming one version of the computer program to another. The C++ source is compiled to produce the object files. The object files are then linked to produce the executable file.
所以你有这些步骤将一个版本的计算机程序转换为另一个版本。编译C ++源代码以生成目标文件。然后链接目标文件以生成可执行文件。
When you run a program you run the executable file. The executable file contains several kinds of information. The first is the machine instructions that are the result of compiling the C++ source code. The other is information that the loader uses in order to know how to load the executable into memory.
运行程序时,运行可执行文件。可执行文件包含几种信息。第一个是编译C ++源代码的结果的机器指令。另一个是加载器使用的信息,以便知道如何将可执行文件加载到内存中。
In the old days, long long ago all libraries and object files were linked together into an executable file and the executable file was loaded by the loader and the loader was pretty simple.
在过去,很久以前所有的库和目标文件都被链接到一个可执行文件中,可执行文件由加载器加载,加载器非常简单。
Then people invented shared libraries and dynamic link libraries and this required the loader to be more complex. Not only does the loader have to load the executable file into memory so that it can start running, the loader must also find any shared libraries or dynamic link libraries that are also needed and load those too. And the loader also has to do a certain amount of linking of the additional components, the shared libraries, so the loader does a lot more than it used to do.
然后人们发明了共享库和动态链接库,这就要求加载器更加复杂。加载器不仅必须将可执行文件加载到内存中才能开始运行,加载器还必须找到所需的任何共享库或动态链接库并加载它们。并且加载器还必须对附加组件(共享库)进行一定量的链接,因此加载器比以前做的要多得多。
#4
2
Object code (within an object file): Output from a compiler intended as input for a linker (for the linker to produce executable code).
对象代码(在目标文件中):来自编译器的输出,用作链接器的输入(用于链接器生成可执行代码)。
Executable: A program ready to be run (executed) on a computer
可执行文件:准备在计算机上运行(执行)的程序
#1
34
Object files are source compiled into binary machine language, but they contain unresolved external references (such as printf
,for instance). They may need to be linked against other object files, third party libraries and almost always against C/C++ runtime library.
目标文件是源代码编译成二进制机器语言,但它们包含未解析的外部引用(例如printf)。它们可能需要与其他目标文件,第三方库以及几乎总是针对C / C ++运行时库链接。
In Unix, both object and exe files are the same COFF format. The only difference is that object files have unresolved external references, while a.out files don't.
在Unix中,object和exe文件都是相同的COFF格式。唯一的区别是对象文件具有未解析的外部引用,而a.out文件则没有。
#2
10
The C++ specification is a technical document in English. For C++11 have a look inside n3337 (or spend a lot of money to buy the paperback ISO standard). In theory you don't need a computer to run a C++ program (you could use a bunch of human slaves, but that would be unethical, inefficient, and unreliable).
C ++规范是英文的技术文档。对于C ++ 11,请查看n3337内部(或花费大量资金购买平装ISO标准)。从理论上讲,你不需要一台计算机来运行一个C ++程序(你可以使用一堆人类奴隶,但那是不道德的,低效的,不可靠的)。
You could have a C++ implementation which is an interpreter, not a compiler (e.g. Ch by SoftIntegration)
你可以有一个C ++实现,它是一个解释器,而不是一个编译器(例如Ch by SoftIntegration)
If you install Linux on your laptop (which I recommend doing to every student) then you could have several free software C++ compilers, in particular GCC and Clang/LLVM (using g++
and clang
commands respectively). Source files are suffixed .cc
, or .cxx
, or .cpp
, or even .C
(I prefer .cc
), and you could ask the compiler to handle a file of some other suffix as a C++ source file (but that is not conventional). Then, both object files (suffixed .o
) and executables share the same ELF format. Conventionally, executables don't have any suffix (e.g. g++
is a binary executable, not doing much except starting other processes like cc1plus
-the compiler proper-, as
-the assembler-, ld
-the linker- etc...)
如果你在笔记本电脑上安装Linux(我建议你对每个学生都这样做)那么你可以有几个免费软件C ++编译器,特别是GCC和Clang / LLVM(分别使用g ++和clang命令)。源文件后缀.cc,或.cxx,或.cpp,甚至.C(我更喜欢.cc),你可以要求编译器处理一些其他后缀的文件作为C ++源文件(但不是常规)。然后,两个目标文件(后缀.o)和可执行文件共享相同的ELF格式。传统上,可执行文件没有任何后缀(例如,g ++是一个二进制可执行文件,除了启动其他进程,如cc1plus - 编译器本身,作为汇编程序,ld-链接器等等)没有做太多工作。
In all cases I strongly recommend:
在所有情况下,我强烈建议:
- to enable all warnings and debug info during compilation (e.g. use
g++ -Wall -g
....) - to improve your source code till you got no warnings
- to learn how to use the debugger (
gdb
) - to be able to build your program on the command line
- to use a version control system like git
- to use a good editor like
emacs
,gedit
,geany
, orgvim
- once you are writing programs in several source files, learn how to use a builder like
make
- to learn C++11 (or even perhaps C++14) rather than older C++ standards
- to also learn other programming languages (Ocaml, Scheme, Haskell, Prolog, Scala, ....) since they would improve your thinking and your way of coding in C++
- to study the source code of several free software coded in C++
- to read the documentation of every function that you are using, e.g. on cppreference or in man pages (for Linux)
- to understand what is undefined behavior (the fact that your program sometimes work does not make it correct).
在编译期间启用所有警告和调试信息(例如使用g ++ -Wall -g ....)
改进你的源代码,直到你没有警告
学习如何使用调试器(gdb)
能够在命令行上构建程序
使用像git这样的版本控制系统
使用像emacs,gedit,geany或gvim这样的好编辑器
一旦你在几个源文件中编写程序,学习如何使用像make这样的构建器
学习C ++ 11(甚至可能是C ++ 14)而不是旧的C ++标准
也学习其他编程语言(Ocaml,Scheme,Haskell,Prolog,Scala,....),因为它们可以改善你的思维和你在C ++中的编码方式
研究用C ++编写的几个*软件的源代码
阅读您正在使用的每个功能的文档,例如在cppreference或手册页(适用于Linux)
了解什么是未定义的行为(您的程序有时工作的事实并不能使其正确)。
Concretely, on Linux you could edit your Hello World program (file hello.cc
) with gedit
or emacs
(with a command like gedit hello.cc
) etc..., compile it using g++ -Wall -g hello.cc -o hello
command, debug it using gdb ./hello
, and repeat (don't forget to use git
commands for version control).
具体来说,在Linux上,您可以使用gedit或emacs(使用gedit hello.cc等命令)编辑Hello World程序(文件hello.cc)等等,使用g ++ -Wall -g hello.cc -o hello编译它命令,使用gdb ./hello调试它,然后重复(不要忘记使用git命令进行版本控制)。
Sometimes it makes sense to generate some C++ code, e.g. by some shell, Python, or awk
script (or even by your own program coded in C++ which generates C++ code!).
有时生成一些C ++代码是有意义的,例如通过一些shell,Python或awk脚本(甚至是你自己用C ++编写的程序,生成C ++代码!)。
Also, understand that an IDE is not a compiler (but runs the compiler for you).
另外,要了解IDE不是编译器(但为您运行编译器)。
#3
4
The languages used for programming computers along with the various software development tools have evolved over the years.
多年来,用于编程计算机的语言以及各种软件开发工具已经发生了变化。
The first computers were programmed with numbers entered by switches on a console.
第一台计算机使用控制台上的开关输入的数字进行编程。
Then people started developing languages and software that could be used to create software more easily and quicker. The first major development was creating assembler language where each line of source was converted by a computer program into a machine code instruction. Along with this came the development of linkers (which link pieces of machine code together into larger pieces). Assemblers were improved by adding a macro or preprocessor facility somewhat like the C/C++ Preprocessor though designed for assembly language.
然后人们开始开发可以更容易,更快速地创建软件的语言和软件。第一个主要的开发是创建汇编语言,其中每行源由计算机程序转换为机器代码指令。随之而来的是连接器的开发(将机器代码片段连接成更大的片段)。通过添加宏或预处理器工具来改进汇编程序,有点像C / C ++预处理器,虽然是为汇编语言设计的。
Then people created programming languages that looked more like people written languages rather than assembler (FORTRAN and COBOL and ALGOL for instance). These languages were easier to read and a single line of source might be converted into several machine instructions so it was more productive to write computer programs in these languages rather than assembler.
然后人们创建的编程语言看起来更像是人们编写的语言而不是汇编程序(例如FORTRAN和COBOL和ALGOL)。这些语言更易于阅读,并且可以将单行源转换为多个机器指令,因此以这些语言而不是汇编程序编写计算机程序会更高效。
The C programming language was a later refinement using lessons learned from the early programming languages such as FORTRAN. And C used some of the same software development tools that already existed such as linkers which already existed. Still later C++ was invented, starting off as a refinement of C introducing object oriented facilities. In fact the first C++ compiler was really a C++ translator which translated C++ source code to C source code which was then compiled with a C compiler. However modern C++ is compiled straight to machine code in order to provide the full functionality of the C++ standard with templates, lambdas, and all the other things with C++11 and later.
C编程语言是后来的改进,使用了早期编程语言(如FORTRAN)的经验教训。 C使用了一些已经存在的相同软件开发工具,例如已经存在的链接器。后来发明了C ++,开始是对C引入面向对象设施的改进。事实上,第一个C ++编译器实际上是一个C ++转换器,它将C ++源代码翻译成C源代码,然后用C编译器编译。然而,现代C ++直接编译为机器代码,以便使用C ++ 11及更高版本的模板,lambdas和所有其他东西提供C ++标准的全部功能。
The basic steps for creating an application from a C or C++ source file are as follows: (1) the source files are created, (2) the source files are compiled (which is really two steps, Preprocessor and compilation), (3) the object files that are created by the C/C++ compiler are linked to create the .exe
从C或C ++源文件创建应用程序的基本步骤如下:(1)创建源文件,(2)编译源文件(实际上是两个步骤,预处理器和编译),(3)由C / C ++编译器创建的目标文件被链接以创建.exe
So you have these steps of transforming one version of the computer program to another. The C++ source is compiled to produce the object files. The object files are then linked to produce the executable file.
所以你有这些步骤将一个版本的计算机程序转换为另一个版本。编译C ++源代码以生成目标文件。然后链接目标文件以生成可执行文件。
When you run a program you run the executable file. The executable file contains several kinds of information. The first is the machine instructions that are the result of compiling the C++ source code. The other is information that the loader uses in order to know how to load the executable into memory.
运行程序时,运行可执行文件。可执行文件包含几种信息。第一个是编译C ++源代码的结果的机器指令。另一个是加载器使用的信息,以便知道如何将可执行文件加载到内存中。
In the old days, long long ago all libraries and object files were linked together into an executable file and the executable file was loaded by the loader and the loader was pretty simple.
在过去,很久以前所有的库和目标文件都被链接到一个可执行文件中,可执行文件由加载器加载,加载器非常简单。
Then people invented shared libraries and dynamic link libraries and this required the loader to be more complex. Not only does the loader have to load the executable file into memory so that it can start running, the loader must also find any shared libraries or dynamic link libraries that are also needed and load those too. And the loader also has to do a certain amount of linking of the additional components, the shared libraries, so the loader does a lot more than it used to do.
然后人们发明了共享库和动态链接库,这就要求加载器更加复杂。加载器不仅必须将可执行文件加载到内存中才能开始运行,加载器还必须找到所需的任何共享库或动态链接库并加载它们。并且加载器还必须对附加组件(共享库)进行一定量的链接,因此加载器比以前做的要多得多。
#4
2
Object code (within an object file): Output from a compiler intended as input for a linker (for the linker to produce executable code).
对象代码(在目标文件中):来自编译器的输出,用作链接器的输入(用于链接器生成可执行代码)。
Executable: A program ready to be run (executed) on a computer
可执行文件:准备在计算机上运行(执行)的程序