一、补充权限
普通用户无法执行sudo:
通过sudo执行后显示不在sudoers file中!(张三不被信任!)
需要修改配置文件(白名单!)
配置文件位于以下目录:
ls /etc/sudoers -l
只有root才能访问这个文件!
通过root账号打开 sudoers文件:
在第100行下面加上对应自己用户名的权限,添加完后保存退出,即使得对应的用户在白名单中。
二、gcc / g++ 编译使用
gcc / g++ 默认生成的可执行程序的名称为a.out
- gcc只能编译c语言;
- g++可以编译c / cpp,编译c也是按照c++的格式编译,但是建议编译c++;
1、编译步骤详解
编译生成可执行程序的步骤:
预处理:
- 预处理(进行宏替换)
其中包括四部分:去注释;头文件展开;条件编译;宏替换
gcc -E mycode.c -o mycode.i
-E : 告诉gcc,从现在开始进行的程序的翻译,将预处理工作昨晚停下来,不要继续往前!
将c文件预处理,生成预处理后的代码(预处理后就不需要头文件!)
条件编译:根据我们写的宏来灵活的进行选择性的编译。
示例:(如果定义的GEBUG这个宏)
#ifedf DEBUG
printf("hello debug\n");
#else
printf("hello release\n");
#endif
除此之外,我们还可以通过不修改代码进行添加宏!
gcc - E mycode.c -o mycode.i -DDEBUG
-DDEBUG
是一个预处理器定义。这意味着在预处理阶段,会定义一个名为 DEBUG
的宏。例如,如果在代码中有 #ifdef DEBUG
这样的条件编译指令,当定义了 DEBUG
这个宏时,相应的代码段就会被包含进来进行处理。
条件编译的应用场景:有的软件分为社区版和专业版,社区版的软件是由免费版的裁切过来的。
预处理之后的代码还为C语言!
编译:
- 编译(生成汇编)
gcc - S mycode.i -o mycode.s
-S : 开始进行程序的翻译,将编译工作做完就停下来!(可以从.c文件到.s)
汇编:
- 汇编(生成机器可识别代码 --- 生成二进制代码)
gcc - c mycode.s -o mycode.o
-c : 开始进行程序的翻译,将汇编工作做完就停下来!(可以从.c文件到.s)
生成的.o文件叫做可重定位目标二进制文件,简称目标文件;在·Windows下被称为.obj文件!
该文件不可以独立执行,虽然已经为二进制文件,但是还需要链接!
可以使用二进制查看工具查看二进制代码
od test.o
链接:
- 链接(生成可执行文件 / 库文件)
gcc test.o -o test
2、库
在我们写c文件的时候,直接调用头文件可以进行库函数的使用,但是头文件中只包含了函数的声明,没有函数的定义!那么函数的声定义位于哪?
函数、方法的实现就在库当中!
库本质其实就是源文件(.c)经过一定的翻译,然后打包 -- 只给自己提供一个文件即可,不用提供太多的库文件;也可以达到隐藏源文件的目的
gtp4o - mini解释如下:
当你在程序中包含一个头文件,比如 #include <stdio.h>
,你会获得库函数,如 printf
的声明。头文件中仅包含函数的原型(即函数的声明),这使得编译器知道如何处理函数调用,并进行类型检查等。
而实际的实现代码则存在于编译器提供的库文件中。例如,在大多数操作系统中,C语言的标准库会被打包成一些动态链接库(如 libc.so
在Linux中,或 msvcrt.dll
在Windows中)或静态库(如 libc.a
)。这些库文件包含了所有标准库函数的实际实现。
结论:
头文件提供方法的声明,库文件提供方法的实现 + 自己的代码 = 可执行程序!
库文件的作用就是我们不用自己进行重复的工作(例如不需要自己实现printf函数)
默认链接的时候,连接的是C的标准库!
当运行到哪一步需要调用函数的时候(链接器告诉去对应的哪里链接对应的库)
在Linux系统中,标准库位于
ls /usr/lib64/libc.so
本质上是一个文件!
- 在Linux系统中, .so(动态库) .a(静态库)
- 在windows系统中 .dll(动态库) .lib(静态库)
库有自己的命名规则:libname.so.xxx(例如libc.so就是c的标准动态库)
云服务器默认安装的只有动态库,没有安装静态库!
将可重定位目标二进制文件和库进行链接生成可执行程序!
- 键盘左上角ESC对应于我们生成的指令!
- iso为每阶段生成的代码 --- 对应于镜像文件!
将可重定位目标二进制文件(经汇编生成的二进制文件)和库进行链接生成可执行程序!
为什么能在给Windows / Linxu上进行 C / C++或者其他形式的开发?
因为我们系统中安装的有C / C++开发相关的头文件 / 库文件!
C / C++开发环境不仅仅指的是vs,gcc,g++,更重要的是,语言本身的头文件和库文件!
在Linux系统中,头文件位于一下路径:
ls /usr/include/
因此,安装vs2019, vs2022等,在安装的时候,要选择对应的开发包,同步也在下载c的头文件和库文件;
即C的头文件和库文件,也在WIndows下存在!如下所示:
编译型语言:安装开发包,必定是下载对应的头文件 + 库文件。
注意点:
- gcc 默认不加选项则直接生成可执行程序。
- 生成的可执行程序不区分后缀名!例如
gcc test.c -o test.txt
文件依旧能正常运行!
-
推荐生成的可执行程序不加后缀名
gcc -o test test.c
-o后面直接加可执行程序名,源代码的位置没有要求!
-
生成的程序不带 -o则默认打印到显示器上;带-o回输入到我们指定的文件中!
-
生成可执行程序的选项中后面跟上的是对应的源代码!
在链接的时候需注意:
- gcc默认链接c的库;
- g++默认链接c++的库
我们的.o和库如何链接?
3、动态链接与静态链接
- 动态链接
动态库不能缺失,一旦对应的动态库缺失,影响的不止是一个程序,可能导致很多程序无法正常运行!
通过ldd指令可以查看一个程序所依赖的动态库(若是静态链接不显示),例如
ldd mytest
Linux系统中好多指令也是用C/C++写的!
ldd /usr/bin/pwd
- 静态链接
在编译器使用静态库进行静态链接的时候,会将自己的方法拷贝到目标程序中,该程序以后不用再依赖静态库!
结论:
- 在Linux中,编译形成的可执行程序,默认采用的就是动态链接 -- 提供动态库!
- 在Linux中,如果要按照静态链接的方式,进行形成可执行程序,需要添加-static选项--提供静态库。
例如:
gcc mycode.c -o mycode-static -static
- 使用静态库生成的可执行程序比使用动态库的体积大!
没有静态库的时候可以自行安装C的静态库,例如在centos7中:
sudo yum install -y glibc-static
如果需要安装C++对应的静态库,可以使用以下:
sudo yum install -y libstdc++ static
结论:
- 如果我们没有静态库,但是我们就要使用static,行不行呢? --- 不行!
- 如果我们没有动态库,只有静态库,而且gcc能找到,gcc依旧能编译,因为gcc默认优先动态链接! -static的本质是:改变优先级!
- 生成的可执行程序不一定纯为动态链接 / 静态链接,可能是混合的!(但是static修饰的一定纯为静态链接!)
file指令
可以查看文件的信息(例如文件的链接库)
file mytest
总结:动态库与静态库的优缺点
- 动态库因为是共享库,可以有效地节省资源(磁盘空间、内存空间、网络空间等)【动态优点】
- 动态库一旦缺失,导致各个程序无法运行;【缺点】
- 静态库不依赖库可以独立运行;【优点】
- 静态库体积大,比较消耗资源【缺点】
4、release与dubug
通过默认的gcc生成的可执行程序是release版本!
debug:可以被追踪调试,形成可执行程序,添加了debug信息(体积一般比release大)
可以通过指定选项来使用debug调试:(加上-g选项)
gcc mycode.c -o mytest-static_debug -sattic -g
可以通过readelf读取可执行程序的代码:
readelf -S mytest_debug
拓展:可执行程序形成的时候,不是无序的二进制构成,而是有自己的格式 -- 可执行程序有自己的二进制格式 -- ELF格式(Linux系统中)
- g++的选项与gcc一致!
- make是一条指令!
- makefile是一个文件!