2022找工作是学历、能力和运气的超强结合体,遇到寒冬,大厂不招人,此时学会c++的话,
我所知道的周边的会c++的同学,可手握10多个offer,随心所欲,而找啥算法岗的,基本gg
提示:系列c++学习的基础和高阶知识,用于公司生产实践中,实实在在的公司部署产品要用的,因为c++速度快,
而java和Python速度慢,自然往硬件里面部署算法啥的,都得用c++或者c,因此本科学的c很重要,后来的Python或者java就没有那么重要了,
c/c++系列文章:
【1】c++:c语言优缺点,visual studio2019如何新建项目,写hello world程序
【2】c/c++:gcc安装,gcc编译hello world文件,system函数调用系统命令,sleep函数
上一节课,我写过hello.c将其编译成可执行文件
这是windows10下的过程
实际上,gcc的编译过程分别是4个步骤:
预处理
编译
汇编
连接
预处理hello.i【参数-E】
编译hello.s【参数-S】
汇编hello.o【二进制机器代码文件,目标文件】【参数-C】
连接hello.exe【可执行文件】【无参数】
命令是:
我们要把下面这个过程分解为四步
gcc -E gan.c -o gan.i
gcc -S gan.i -o gan.s
gcc -C gan.s -o gan.o
gcc gan.o -o gan1
这步骤我没有成功
但是呢
就这四个步骤,你得熟悉
std标准库io是输入输出库
void最好是写,没有输入参数
可以不写,也是无参数
main必须有,程序中必须有,且只有一个,表示程序启的入口
//单行注释
/**/多行注释,块注释
f();函数调用完事冒号结束
{}函数主体,到此完事
return 0;程序正常结束
如果程序其他的还需要停止就需要调用系统函数system(“系统命令”);
windows.h文件别忘了哦,不会查百度
整个代码文件需要是.c结束的文件哦
这是c
c++才是后面的东西
visual studio可以编译c文件
你当然也可以用txt文件写,改为.c后缀
用gcc编译即可
sleep是休眠函数,休眠多少ms吧
gcc预处理 -E 生成.i文件【预处理文件】
编译 -S 生成.s文件【汇编文件】
汇编 -c 生成目标文件.o【目标文件】
连接 无参数 生成可执行文件.exe【可执行文件】
反正四个步骤,你可以浓缩为一个步骤即可
好说
待会我们继续讲
gcc预处理 -E 生成.i文件【预处理文件】
gcc -E hello.c -o hello.i
.i是预处理文件哦
我们去看看.i文件,是啥东西?
预处理完成的是,头文件展开的工作
把头文件里面的内容,整体给你展开,方便咱们main函数后续使用头文件的各种函数
你去看看hello.i文件,里面和hello.c的区别就是
hello.i的头文件一大堆,后面的代码和.c文件一样的
所以预处理处理的就是头文件。
不检查语法错误哦。
可以展开任意文件,但是错误不错误不知道。
在c语言中,.h就行,它不管,只看是否为.h文件即可。
咱们如果里面不写.h,而是写别的后缀文件
比如写一个hello.x
你再预处理试试
D:\AWYY\leetcode\cplus\test>gcc -E hello.c -o hello2.i
hello.c:2:10: fatal error: xxx.x: No such file or directory
#include "xxx.x" //用户自定义的
^~~~~~~
compilation terminated.
gg了看到了吗
完成任务终止
失败了呗
但是这无大碍,因为我们没有xxx.x文件啊
它报错是因为没有这个文件
如果有呢?
咱们加上文件
你在编译试试
D:\AWYY\leetcode\cplus\test>gcc -E hello.c -o hello2.i
D:\AWYY\leetcode\cplus\test>
成功了
然后你看看hello2.i
里面是啥
# 1 "hello.c"
# 1 ""
# 1 ""
# 1 "hello.c"
# 1 "xxx.txt" 1
1111
2222
3333
# 3 "hello.c" 2
int main(void)
{
printf("调用cmd命令");
system("pause");
}
你看看,预处理干了什么?
不就是把这txt头文件内部的东西给导入到我这个文件里面了吗?
所以,懂了没,gcc预处理就是第一步,把头文件导入,我估计python的import就是这个意思也是要导入的头文件的,那些函数我们需要用。
但是不查错的哦。
#include
//#include "xxx.txt" //用户自定义的
#define PI 3.14 //宏定义常量PI
int main(void)
{
printf("hello world\n");
printf("d%", PI); //打印PI
}
你再编译时时
D:\AWYY\leetcode\cplus\test>gcc -E hello.c -o hello2.i
D:\AWYY\leetcode\cplus\test>
看看.i文件什么情况
# 6 "hello.c"
int main(void)
{
printf("hello world\n");
printf("d%", 3.14);
}
发现了啥?
PI变3.14了
所以说预处理,直接将宏定义的常量直接用常量替换了。
即宏名替换为宏值
另外,你看看,那些注释跑哪里去了????
没了
相当于将注释直接废掉,用空字符替代了
这也是预处理的功能之一
美滋滋。
还有,展开条件编译,怎么说呢
#include
//#include "xxx.txt" //用户自定义的
#define PI 3.14 //宏定义常量PI
int main(void)
{
printf("hello world\n");
printf("d%", PI); //打印PI
#ifdef PI
printf(1);//如果上面定义了PI,则打印1
#endif
}
编译试试
D:\AWYY\leetcode\cplus\test>gcc -E hello.c -o hello2.i
D:\AWYY\leetcode\cplus\test>
# 6 "hello.c"
int main(void)
{
printf("hello world\n");
printf("d%", 3.14);
printf(1);
}
因为PI定义了,所以一定要打印
条件编译
这种就预处理也要搞的事情。
懂?
编译 -S 生成.s文件【汇编文件】
咱们直接将hello.i
用命令编译
D:\AWYY\leetcode\cplus\test>gcc -S hello.i -o hello.s
hello.c: In function 'main':
hello.c:7:2: warning: implicit declaration of function 'system' [-Wimplicit-function-declaration]
{
^
编译之后的文件叫做汇编文件
汇编语言写的文件,顾名思义
.file "hello.c"
.text
.def __main; .scl 2; .type 32; .endef
.section .rdata,"dr"
.LC0:
.ascii "\265\367\323\303cmd\303\374\301\356\0"
.LC1:
.ascii "pause\0"
.text
.globl main
.def main; .scl 2; .type 32; .endef
.seh_proc main
main:
pushq %rbp
.seh_pushreg %rbp
movq %rsp, %rbp
.seh_setframe %rbp, 0
subq $32, %rsp
.seh_stackalloc 32
.seh_endprologue
call __main
leaq .LC0(%rip), %rcx
call printf
leaq .LC1(%rip), %rcx
call system
movl $0, %eax
addq $32, %rsp
popq %rbp
ret
.seh_endproc
.ident "GCC: (x86_64-posix-seh-rev0, Built by MinGW-W64 project) 7.3.0"
.def printf; .scl 2; .type 32; .endef
.def system; .scl 2; .type 32; .endef
这些都是汇编指令
汇编是连接c语言和机器指令的语言
所以:gcc编译的过程,就是将c语言汇编为汇编语言
如果代码有错误,无法汇编成功
生成失败就会删除那个代码
汇编的功能之一就是逐行检查代码的正确性。这是整个编译过程中最耗时的。
汇编 -c 生成目标文件.o【目标文件】
现在的话,我们就要汇编了
将s文件,生成为目标文件.o
D:\AWYY\leetcode\cplus\test>gcc -c hello.s -o hello.o
注意,参数是c哦
不是别的大C啥的,否则汇编不成功
txt打开是乱码了
实际上文件里面是二进制的机器指令
反正你要知道,这是目标文件即可
将汇编指令翻译为机器可以识别的二进制代码
因为机器才能认识那些指令,我们人是记不住的
因为记不住,才造出来汇编语言,汇编也麻烦,所以后来发明了c语言
c语言大家嫌麻烦,所以后来出现了c++和python,java等等等等
懂吧???
所以,高级语言在运行之前,需要把这些工作做好,然后一步步往下转
翻译为机器语言
连接 无参数 生成可执行文件.exe【可执行文件】
okay,这波我们就可以去生成可执行文件了
D:\AWYY\leetcode\cplus\test>gcc hello.o -o hello
D:\AWYY\leetcode\cplus\test>hello.exe
调用cmd命令请按任意键继续. . .
D:\AWYY\leetcode\cplus\test>
懂了吧
gcc四个步骤,就这么来的
当然你可以一步到位
D:\AWYY\leetcode\cplus\test>gcc hello.c -o hello2
D:\AWYY\leetcode\cplus\test>hello2.exe
hello world
D:\AWYY\leetcode\cplus\test>
但是你要知道gcc的4个步骤,一步一步都是怎么来的,懂?
如果你用hello.c
直接用参数S,它就会跳过预处理阶段,直接生成汇编文件
直接用参数c,它就会跳过预处理和编译阶段,直接生成目标文件
直接不用参数,它就会跳过预处理,编译和链接,直接生成可执行文件
懂?
提示:重要经验:
1)
2)学好c++,即使经济寒冬,手握10个大厂offer绝对不是问题!
3)笔试求AC,可以不考虑空间复杂度,但是面试既要考虑时间复杂度最优,也要考虑空间复杂度最优。