c primer plus c++ primer plus,c++primer plus视频教程
在本文中,变量、宏和结构在目录目标代码、可执行文件和库编译原理头文件中声明,而变量和函数在C文件中定义。详细解释了GCC参数的示例。
1.预处理以生成。预处理程序
2.将预处理文件转换成汇编语言生成文件。编译程序
3.有文件【汇编器as】编译成目标代码(机器码)生成。o.
4.连接目标代码生成可执行程序[链接器ld]
在Linux中,C源文件的扩展名是。C,而C源文件的扩展名是。c或者。cpp。
选择权
功能描述
表示“具有…性质的”
生成目标文件,可以是。我,s和。o文件。
-E
仅运行c预编译器。
-丙
通知gcc取消链接,只编译生成的目标文件,不做最后的链接。
-墙
生成所有警告消息
-w
不会生成任何警告信息。
我
指定头文件的目录路径。
-我
指定库文件的目录路径。
-静态
链接到静态库
-g
包括调试信息。
-v
编译时输出命令行、编译器版本等信息。
-韦罗
将所有警告消息转换为错误消息,并在出现警告时终止编译。
-O0
关闭所有优化选项。
-O1
最基本的优化级别
-氧气
在推荐的优化级别下,编译器将尝试提高代码的性能,而不会占用大量存储空间和花费大量编译时间。
-臭氧
最高级别的优化会延长编译时间。
目标代码、可执行文件和库的编译器将源代码转换成中间代码(即目标代码obj、binary,缺少启动代码(程序与操作系统的接口)和不同平台所需的库函数);链接器将中间代码与其他代码(预编译库代码和启动代码)组合生成可执行文件exe;目标代码(由编译器翻译)、启动代码(由链接器实现以匹配不同的操作系统)、库代码(由链接器实现,复制复制附加帮助代码=可执行文件。
在编译原理的预处理阶段,得到原生程序(头文件被相应的代码替换,但printf函数没有被替换)
找到C中的头文件,对头文件中包含的宏、变量、函数声明、嵌套头文件、依赖、宏替换、检查重复定义和声明进行处理,将所有内容扫描到当前C文件中,形成中间文件。(文件拼接过程,动态编译)
因为宏# include“xx.h”实际上是删除当前行,在当前行插入xx . h的内容。因为要写这些函数声明的地方很多(xx.h中每个调用函数的地方都要在使用前声明一次),所以使用宏# include“xx . h”简化了很多行代码——让预处理程序自己替换。
在编译阶段,中间文件根据某些标准被转换成二进制目标文件。
将中间文件编译成二进制代码,并根据特定的目标文件格式生成目标文件。在这种格式中,目标文件的所有全局变量和函数的符号描述将根据标准组织成一个目标文件(obj,binary)。
静态编译:
这样,我们要做的就是写出包含函数、类等声明的头文件(a.h,b.h,… B.H,…)。以及它们对应的实现文件(a.cpp,b.cpp,…),编译器会把它们编译成静态库文件(a.lib,b.lib,…)。在后续的代码重用过程中,我们只需要提供相应的头文件(。h)和相应的库文件(。lib)来使用过去的代码。
通过头文件调用库函数。在很多场合,源代码不方便(或者不允许)发布给用户,只要把头文件和二进制库提供给用户就可以了。用户只需要根据头文件中的接口声明调用库函数,不必关心接口是如何实现的。编译器将从库中提取相应的代码。头文件可以加强类型安全检查。如果接口的实现或使用方式与头文件中的声明不一致,编译器会指出错误。这个简单的规则可以大大减轻程序员调试和纠错的负担。
链接和重定位每个目标文件的函数和变量。目标文件中的二进制代码和一些附加代码按照一定的规范集成到一个可执行文件中。
在这个阶段,我们将关注# include中函数的具体实现。
在头文件中,声明变量、宏和结构,而变量和函数在C文件中定义。如果头文件中定义了一个函数体,是否设置为局部函数?链接时会发现多个函数并报错。如果在头文件中定义了一个全局变量并赋予了一个初始值,那么在引用这个头文件的多个C文件中都有相同变量名的副本,这些副本存在于数据段中。在链接阶段,数据段中有多个相同的变量。如果没有给初始值,变量将被放在BSS段中,链接器将只为BSS段中同名的多个变量分配一个存储空间。许多C文件使用的数据结构的集中管理。一方面可以封装实现过程,另一方面可以提供头文件作为调用接口的参考。主函数是标准C/C的程序入口,编译器会先找到函数所在的文件。
示例# includesdio.h
#包含stdlib.h
#包含字符串. h
#定义页面大小4096
#定义MAX_SIZE 100*PAGE_SIZE
int main()
{
char * buf=(char *)malloc(MAX _ SIZE);
memset(buf,0,MAX _ SIZE);
printf(缓冲区地址=0x%p\n ,buf);
免费(buf);
返回0;
}预处理:aaarch 64-Linux-GNU-gcc-etest . C-otest . I-e只运行C预编译器。测试一:
.
extern char * _ _ stpcpy(char * _ _ restrict _ _ dest,const char *__restrict __src)
_ _ attribute _ _((_ _ not row _ _,_ _ leaf _ _)_ _ attribute _ _((_ _ nonnull _ _(1,2)));
extern char * STP cpy(char * _ _ restrict _ _ dest,const char *__restrict __src)
_ _ attribute _ _((_ _ not row _ _,_ _ leaf _ _)_ _ attribute _ _((_ _ nonnull _ _(1,2)));
extern char * _ _ stpncpy(char * _ _ restrict _ _ dest
const char *__restrict __src,size_t __n)
_ _ attribute _ _((_ _ not row _ _,_ _ leaf _ _)_ _ attribute _ _((_ _ nonnull _ _(1,2)));
extern char * stpncpy(char * _ _ restrict _ _ dest,
const char *__restrict __src,size_t __n)
_ _ attribute _ _((_ _ not row _ _,_ _ leaf _ _)_ _ attribute _ _((_ _ nonnull _ _(1,2)));
# 499 /usr/include/string.h 3 4
# 4 测试. c 2
# 8 测试. c
int main()
{
char * buf=(char *)malloc(100 * 4096);
memset(buf,0,100 * 4096);
printf(缓冲区地址=0x%p\n ,buf);
免费(buf);
返回0;
}编译:一个Arch 64-Linux-GNU-GCC-S测试。输入输出测试。S-S只激活预处理和编译,也就是把文件编译成汇编代码。测试. s。拱形臂v8-a。文件 test.c 。文本。部分。常量数据。对齐3
. LC0:字符串“缓冲区地址=0x%p\n”。文本。对齐2。全球干线。主类型,%函数
主要:
. LFB6:cfi_startproc
stp x29,x30,[sp,-32]!cfi_def_cfa_offset 32。cfi_offset 29,-32。cfi_offset 30,-24
mov x29,sp
mov x0,16384
movk x0、0x6、lsl 16
bl malloc
字符串x0,[sp,24]
mov x2,16384
movk x2,0x6,lsl 16
mov w1,0
ldr x0,[sp,24]
bl内存集
ldr x1[sp,24]
adrp x0, LC0
添加x0,x0,lo12:LC0
bl printf
ldr x0,[sp,24]
bl免费
mov w0,0
ldp x29,x30,[sp],32。cfi_restore 30。cfi_restore 29。cfi_def_cfa_offset 0
浸水使柔软。cfi_endproc
. LFE6:主要尺寸,-主。 GCC:(Debian 9 . 2 . 1-28)9 . 2 . 1 2020 02 03 。section.note.gnu-stack,,@ progbits assembly aaarch 64-Linux-GNU-gcc-CT est . s-otest . o-c只激活预处理、编译、汇编,也就是他只把程序链接到obj文件。aarch 64-Linux-GNU-gcc test . o-o test-static . static这个选项将禁止使用动态库。所以编译出来的东西一般都比较大,不需要任何动态连接库就可以运行。
默认链接C语言标准库(libc),Linux内核中的库分为两类:动态链接库和静态链接库。GCC优先考虑动态链接库。使用- static参数使测试程序静态链接到C语言标准库。本书书:Linux项目# ls -l
共计628人
-rwxr-xr-x1 root root 576808 Aug 29 08:17测试
-rw-rw-r - 1本书书本书书271 8月29日08:07 test.c
-rw-r - r - 1根根52343 8月29日08:10测试
-rw-r - r - 1根根1824年8月29日08:15测试
-RW-R-R-1 root root 756 aug 29 08:13 test . s以ARM64 GCC十字工具链为例。
C标准库的动态库地址为/usr/arm-Linux-gnueabi/lib/libc . so . 6静态库地址为/usr/aaarch 64-Linux-GNU/lib/libc . a
,
郑重声明:本文由网友发布,不代表盛行IT的观点,版权归原作者所有,仅为传播更多信息之目的,如有侵权请联系,我们将第一时间修改或删除,多谢。