计算机只能理解一种语言,而这种语言由一组由 1 和 0 组成的指令组成。这种计算机语言被恰当地称为机器语言。对计算机的一条指令可能如下所示:
00000 | 10011110 |
---|
如果你想计算两个数字的总和,作为机器语言程序可能指令长这样:
00000 | 10011110 |
---|---|
00001 | 11110100 |
00010 | 10011110 |
00011 | 11010100 |
00100 | 10111111 |
00101 | 00000000 |
因此,还是得搞点高级语言,毕竟代码是死的,人是活的,活人就会犯错。哪个更容易检查,书写,看懂 别人的代码 显而易见。如下所示的c++代码和上面的机器语言干的活一样:
int a, b, sum;
cin >> a;
cin >> b;
sum = a + b;
cout << sum << endl;
人说人话高级语言,机器只听机器语言,各种compilers, interpreters, assemblers 干的事情就是当翻译。
compiler | interpreter | assembler |
---|---|---|
把高级语言转成机器语言,一次性全转 | 把高级语言转成机器语言,一行一行的转 | 把汇编语言转成机器语言 |
C ,C++ | Ruby,Perl,Python,PHP | 汇编语言 |
C++被设计成一种编译型语言,也就是说c++代码一般被翻译成系统可以直接理解的机器语言,使得生成的程序非常高效。为此,需要一组工具,称为开发工具链(development toolchain),其核心是编译器(complier)及其链接器(linker)。
chatGPT解释开发工具链:
开发工具链(development toolchain)是一组工具和软件的集合,用于编写、编译、调试和部署软件应用程序。对于C++这样的编译型语言,开发工具链尤为重要,因为它们负责将人类可读的源代码转换为计算机可执行的机器语言。下面是开发工具链的主要组成部分:
- 文本编辑器:开发工具链的起点通常是文本编辑器,程序员用它来编写源代码。常见的文本编辑器包括Visual Studio Code、Sublime Text、Atom等。
- 编译器(Compiler):编译器是开发工具链的核心部分,负责将高级语言(如C++)编写的源代码转换为机器语言。对于C++,常见的编译器包括GNU Compiler Collection(GCC)、Clang等。编译器将源代码文件编译成目标文件(object files),这些文件包含机器代码的二进制表示。
- 链接器(Linker):链接器将编译器生成的目标文件以及任何必要的库文件连接在一起,创建一个可执行的程序。它负责解决外部符号引用、符号重定位等问题。在C++开发中,链接器起到了很重要的作用,尤其是在引入外部库、静态库和动态链接库时。常见的链接器包括GNU ld、Microsoft Link等。
- 调试器(Debugger):调试器是开发过程中的关键工具,用于诊断和修复代码中的错误(bug)。它允许开发人员逐行执行代码、查看变量的值以及跟踪程序执行过程。常见的调试器包括GDB、LLDB、Visual Studio Debugger等。
- 构建工具(Build Tools):构建工具用于自动化和管理项目的构建过程。它们可以处理依赖关系、编译源代码、链接目标文件,并执行其他必要的任务,以确保项目的正确构建。在C++开发中,常用的构建工具包括Make、CMake、Bazel等。
- 性能分析工具(Performance Profilers):性能分析工具帮助开发人员评估程序的性能并识别性能瓶颈。它们可以提供关于CPU使用情况、内存分配情况和函数调用频率等信息。常见的性能分析工具包括Valgrind、gprof、Intel VTune等。
以上是开发工具链中的一些关键组件,它们共同构成了一个完整的开发环境,使程序员能够高效地开发、调试和优化C++应用程序。
已经有点看得云里雾里了,但是没关系。工具链 = 干活全家桶 ,这样是不是非常的好归类。
red panda dev c++是一款国人开发的IDE(Integrated Development Environment,IDE),可以理解成上面1-6的全家桶软件放到一个软件里。
但是都是全家桶套餐,肯德基和麦当劳都能吃饱,但里面侧重什么还是有些不同的。👉 不同的IDE对于C++的特性会选择程序不同的部分进行实现,编译器是比较关键的区别。
dev-c++(red panda dev c++的参考软件,但是后面没继续开发了):MinGW or TDM-GCC 作为底层编译器。
这一点在运行下方代码的时候:
test.cpp
是文件的名字,test就是测试的意思,.cpp
就是一种格式,类似word大多都叫XXXX.docx#include <iostream>
using namespace std;
int main()
{
string x;
cin >> x;
cout << x;
}
tools output 得到下方的内容,()内的内容是自己添加的
- Filename: D:/libregd/c++/test.cpp (*a.)
- Compiler Set Name: MinGW GCC 11.2.0 64-bit Debug (*b.)
Processing C++ source file: (*c.)
------------------
C++ Compiler: D:/libregd/RedPanda-Cpp/MinGW64/bin/g++.exe (*d.)
Command: g++.exe "D:/libregd/c++/test.cpp" -o "D:/libregd/c++/test.exe" -g3 -pipe -Wall -Wextra (*e.运行了一条命令)
Compile Result:(*f. )
------------------
- Errors: 0 (*g. )
- Warnings: 0 (*h. )
- Output Filename: D:/libregd/c++/test.exe (*i. )
- Output Size: 166.63 KiB (*j. )
- Compilation Time: 0.374 secs (*k. )
让我们开始做一些整理:
*编号 | 含义 |
---|---|
a. | 文件名字不仅有文件名字,还有文件名字所处的位置 |
b. | 编译器也有名字 |
c. | 开始编译了 |
d. | 编译器的地址和程序名字 |
e. | 运行了一条命令 |
f. | 结果,有结果说明运行成功了 |
g. | 说明是0错误,自动帮你检查的,基于别的程序员们写好的检查规则 |
h. | 警告0,原理同上 |
i. | 输出了一个文件, test.exe ,和.cpp 同名,但格式不同了 |
j. | test.exe 的文件大小 |
k. | 编译过程的使用时间,0.374秒 |
里面其实已经涵盖了很多内容了,只是乍一看感觉啥也没说。
/
有的\
Q:D:/libregd/c++
? 我在windows下的文件不都是D:\libregd\c++
这样吗?(说着打开一个文件管理器,查看路路径)
A:这是一个历史遗留问题,就像手机是安卓还是苹果一样,这里说明g++.exe
还是以linux的标准来做事,针对windows做了一些小小的内部一键转换。
总结
越是靠近现代的编程生态软件,越使用linux的标准。
Q: Command: g++.exe "D:/libregd/c++/test.cpp" -o "D:/libregd/c++/test.exe" -g3 -pipe -Wall -Wextra
这条命令怎么理解?
A:chatGPT:
这个命令是使用GNU编译器(g++)将一个名为 "test.cpp" 的源代码文件编译成一个可执行文件,并指定输出文件名为 "test.exe"。下面是对命令中各部分的解释:
- g++.exe: 这是GNU编译器的可执行文件。在Windows系统中,".exe" 扩展名表示可执行文件。
- "D:/libregd/c++/test.cpp": 这是待编译的源代码文件的路径。在这个例子中,源代码文件名为 "test.cpp",位于 "D:/libregd/c++/" 目录下。路径被双引号括起来,是因为路径中包含了空格,这样可以确保路径被正确解析。
- -o "D:/libregd/c++/test.exe": 这是指定编译器生成的可执行文件的输出路径和名称。在这个例子中,可执行文件将被命名为 "test.exe" 并保存在 "D:/libregd/c++/" 目录下。同样地,路径被双引号括起来。
- -g3: 这是一个编译选项,表示生成调试信息。"-g" 选项后面的数字表示调试信息的详细程度,这里的 "3" 表示生成最详细的调试信息,有助于在调试器中进行精确的源代码级别调试。
- -pipe: 这是一个编译选项,告诉编译器在编译过程中使用管道来加速编译。
- -Wall: 这是一个编译选项,表示开启所有警告信息。编译器将尽可能地检测代码中潜在的问题,并给出警告信息。
- -Wextra: 这是一个编译选项,表示开启额外的警告信息。它会启用一些额外的警告,帮助开发者捕捉更多潜在的问题。
这个命令会将 "test.cpp" 编译成一个带有调试信息的可执行文件,并将其命名为 "test.exe",保存在指定路径下。
Q:显而易见这是在windows下的command ,在linux下这个命令会是如何呢?
chatGPT:
在Linux下,相同的命令也可以使用,只是路径分隔符和可执行文件的扩展名会有所不同。下面是相同的命令在Linux下的写法:
g++ "D:/libregd/c++/test.cpp" -o "D:/libregd/c++/test" -g3 -pipe -Wall -Wextra
在Linux下的主要区别有:
- 路径分隔符不同:Linux下使用的路径分隔符是斜杠(/),而不是Windows下的反斜杠(\)。
- 可执行文件没有扩展名:在Linux下,可执行文件通常不包含扩展名,所以输出文件名只是 "test",而不是 "test.exe"。
其余部分的命令格式和含义与在Windows下是相同的。
总结
看来自由度还是自己终端运行command的好。
Q: Output Size: 166.63 KiB ,看起来KiB 是一种单位?能帮我科普相关的常识吗?用词简洁精要,有表格的话更好。
当谈论计算机存储容量时,常用的单位包括字节(Byte)、千字节(Kilobyte,KB)、兆字节(Megabyte,MB)、吉字节(Gigabyte,GB)等。而KiB则是其中的一种更精确的单位,表示“二进制千字节”(Kibibyte)。
下面是常见存储容量单位的表格:
单位 简称 等于 字节 B 1字节 千字节 KB 1,000字节 (10^3) 兆字节 MB 1,000,000字节 (10^6) 吉字节 GB 1,000,000,000字节 (10^9) TiB TB 1,000,000,000,000字节 (10^12) PiB PB 1,000,000,000,000,000字节 (10^15) EiB EB 1,000,000,000,000,000,000字节 (10^18) ZiB ZB 1,000,000,000,000,000,000,000字节 (10^21) YiB YB 1,000,000,000,000,000,000,000,000字节 (10^24) KiB(Kibibyte)与KB(Kilobyte)的区别在于,KB是指1000字节,而KiB是指1024字节。在计算机领域,通常会使用二进制单位(如KiB、MiB、GiB等)来更精确地表示存储容量,特别是在涉及到计算机内存、硬盘容量等方面。
总结
这么看Kib更符合计算机的规则了,但日常大家也就是KB啥的用一用,比较方便,符合直觉,现实生活也是10进制的嘛。
Q:Compilation Time: 0.374 secs
这个时间很短,而且我想知道过程到底干了啥?
A: chatGPT 给出的建议是需要考虑使用命令,也就是MINGW64
,
你可以使用命令行工具来查看编译器的详细输出,其中可能包含编译时间的信息。具体的命令取决于你所使用的编译器。
在你的情况下,你使用的是g++编译器,你可以通过在命令行中添加
-ftime-report
选项来生成编译时间的报告。这个选项会显示编译过程中各个阶段所花费的时间。例如,你可以这样使用命令进行编译:(
test1.cpp
和上面test.cpp
内容完全一样)g++.exe test1.cpp -o test1.exe -ftime-report
编译完成后,编译器会输出详细的编译时间报告,其中包含了每个阶段的耗时信息,你可以从中找到编译过程所用的时间。
采用这个办法确实生成得到了一个新的test1.exe,而且通过在命令行里 ./test1.exe
,可以运行
下面则是-ftime-report
给出的内容:
| Phase | Time (wall) | Time (%) | Memory (sys) | Memory (%) |
|--------------------------------|-------------|----------|--------------|------------|
| Phase setup | 0.00 | 1% | 1582k | 4% |
| Phase parsing | 0.21 | 86% | 37M | 86% |
| Phase lang. deferred | 0.02 | 9% | 4042k | 9% |
| Phase opt and generate | 0.01 | 4% | 402k | 1% |
| Name lookup | 0.03 | 12% | 1663k | 4% |
| Overload resolution | 0.02 | 10% | 2906k | 7% |
| Preprocessing | 0.04 | 17% | 1796k | 4% |
| Parser (global) | 0.04 | 15% | 14M | 34% |
| Parser struct body | 0.04 | 16% | 6858k | 16% |
| Parser function body | 0.01 | 6% | 2362k | 5% |
| Parser inl. func. body | 0.01 | 6% | 1421k | 3% |
| Parser inl. meth. body | 0.02 | 7% | 2867k | 6% |
| Template instantiation | 0.07 | 29% | 11M | 27% |
| TOTAL | 0.24 | - | 43M | - |
总结
phase parsing
对于这段代码来说,时间花最多。
通过同样的内容的cpp文件编译的,只不过一个在redpanda dev 里,一个在MINGW64 命令行里:
test.exe 167kb
test1.exe 130kb
我想知道这种区别如何导致的,结论是-g
具有很大的影响。
名称 | 使用的编译参数(前面都是 g++ test1.cpp -o testX.exe) | 大小(kb) |
---|---|---|
test1.exe | -ftime-report | 130 |
test2.exe | -ftime-report -finput-charset=UTF-8 -fexec-charset=gbk -g3 -pipe -Wall -Wextra | 251 |
test3.exe | -ftime-report -g3 -pipe -Wall -Wextra | 251 |
test4.exe | -ftime-report -g3 -pipe -Wall | 251 |
test5.exe | -ftime-report -g3 -pipe | 251 |
test6.exe | -ftime-report -g3 | 251 |
test7.exe | -ftime-report -g2 | 178 |
test8.exe | -ftime-report -g1 | 133 |
chatGPT:
-g
参数是用来生成调试信息的,它会将调试符号包含在可执行文件中,以便在调试程序时使用。因此,加入-g
参数会增加可执行文件的大小。在你的第一条命令中,你没有加入
-g
参数,因此编译器并没有生成调试信息,所以可执行文件的大小相对较小。而在第二条命令中,你加入了
-g3
参数,它会生成更多的调试信息,因此可执行文件的大小会更大。通常,较大的调试信息对于深度调试来说很有用,但是在生产环境中,你可能会想要将这些信息删除以减小可执行文件的大小。所以,如果你不需要进行深度调试,可以省略
-g
参数,以减小可执行文件的大小。
总结
高手用终端干活也不是没有道理,不过普通环境估计还是找个趁手的IDE就行了,初学者,我感觉啥都能凑活上。
也许windows 还是有些局限,可以使用在线的网站作为学习c++的入门来用:cpp.sh
这个网站提供了c++98,c++11,c++14,c++17,c++20,c++23作为可选的运行标准。
也可以尝试根据关键词在线c++ 获得一些别的更适合的在线可以运行c++代码的网站,比如发现了一篇几款优秀的支持C、C++在线编译器
就像iPhone 4 一路到iphone15一样,语言本身是动态发展的,就像2000年以前“牛逼”也不是一个夸人的词。
c++ 本身作为一门语言也是不断发展的。98,11,20,23,这些数字指代的是年份,那一年推出的新标准。
本笔记采用c++11作为学习的环境是因为参考的教程内容也是11年的。