C程序编程四步走(c编程步骤)

任何一个 C 程序代码到生成一个可执行文件都需要四步,分别是预处理 Pre-processing ,编译 Compiling ,汇编 Assembling 和链接 Link ,这里借助 Gcc 工具来探究这四步分别做了什么事,起到什么样的作用。本文使用的测试代码是经典入门程序 "Hello World!"。

测试环境

为探究预处理,编译,汇编和链接的功能,我们在 Ubuntu 系统中使用 gcc 编译器( version=4.8.4 ),简单的也是最经典的入门程序 "Hello World!" 作为测试代码。源文件 hello.c[1] 代码如下:

// filename: hello.c# include <stdio.h>int main(void){ printf("Hello World!"); return 0;}

正常情况我们都会执行命令 gcc hello.c -o hello.out 来生成二进制可执行程序 hello.out。

预处理[2]

C 预处理器是用在编译器处理程序之前,它预扫描源代码完成包含头文件宏扩展条件编译行控制等功能。对于测试代码中,预处理器只对头文件进行了处理。获取预处理器输出的结果使用该命令 gcc -E hello.c -o hello.i。由于 hello.i[3] 文件内容比较多,这里截取部分进行说明。

// filename: hello.i# 1 "hello.c"# 1 "<built-in>"# 1 "<command-line>"# 1 "/usr/include/stdc-predef.h" 1 3 4# 1 "<command-line>" 2# 1 "hello.c"...# 1 "/usr/lib/gcc/x86_64-linux-gnu/4.8/include/stddef.h" 1 3 4# 212 "/usr/lib/gcc/x86_64-linux-gnu/4.8/include/stddef.h" 3 4typedef long unsigned int size_t;...# 5 "hello.c" 2int main(){ printf("Hello World!"); return 0;}

Tips:
hello.i 中有很多这样的格式
# line filename flags,它表示下面行是由文件 filename 的第 line 行生成的。其中 flags 有 1,2,3,4 四种取值

• 1 代表新文件的开始

• 2 代表返回一个文件

• 3 代表下面的文本来自系统头文件,所以某些警告可以过滤掉

• 4 代表下面的文本应该包含在extern C块中 按照提示 stddef.h 文件中第 212 行有 size_t 的宏定义。

编译[4]

编译的过程是将某种编程语言写的源代码(这里特指 C 语言)转换成另一种编程语言(这里特指汇编语言)。前面我们将 hello.c 预处理成了 hello.i 文件,现在就要将 hello.i 文件编译成汇编文件 hello.s 。获取编译器输出的结果使用命令 gcc -S hello.i -o hello.s 。汇编结果见 hello.s[5]

.file "hello.c" .section .rodata .LC0: .string "Hello World!" .text .globl main .type main, @function main: .LFB0: .cfi_startproc pushq %rbp .cfi_def_cfa_offset 16 .cfi_offset 6, -16 movq %rsp, %rbp .cfi_def_cfa_register 6 movl $.LC0, �i movl $0, �x call printf movl $0, �x popq %rbp .cfi_def_cfa 7, 8 ret .cfi_endproc .LFE0: .size main, .-main .ident "GCC: (Ubuntu 4.8.4-2ubuntu1~14.04.3) 4.8.4" .section .note.GNU-stack,"",@progbits

汇编[6]

汇编的过程是将汇编语言编写的源码转换成可执行的机器代码,通常目标文件中包含至少两个段:代码段和数据段。其中代码段包含程序的指令,一般可读和可执行,不可写;数据段用来存放程序中所用到的各种全局变量或静态数据,一般可读,可写,可执行。获取汇编器输出的结果使用该命令 gcc -o hello.o -c hello.c ,由于 hello.o 是二进制文件,是无法阅读的。这里我们通过命令 objdump 来对二进制文件进行反汇编,查看里面内容。

// objdump -d hello.o 查看hello.o中代码段信息hello.o:文件格式 elf64-x86-64Disassembly of section .text:0000000000000000 <main>: 0: 55 push %rbp 1: 48 89 e5 mov %rsp,%rbp 4: bf 00 00 00 00 mov $0x0,�i 9: b8 00 00 00 00 mov $0x0,�x e: e8 00 00 00 00 callq 13 <main 0x13> 13: b8 00 00 00 00 mov $0x0,�x 18: 5d pop %rbp 19: c3 retq

hello.o中各段信息如下:

// objdump -h hello.o 显示hello.o中各个段的头部信息hello.o:文件格式 elf64-x86-64节:Idx Name Size VMA LMA File off Algn 0 .text 0000001a 0000000000000000 0000000000000000 00000040 2**0 CONTENTS, ALLOC, LOAD, RELOC, READONLY, CODE 1 .data 00000000 0000000000000000 0000000000000000 0000005a 2**0 CONTENTS, ALLOC, LOAD, DATA 2 .bss 00000000 0000000000000000 0000000000000000 0000005a 2**0 ALLOC 3 .rodata 0000000d 0000000000000000 0000000000000000 0000005a 2**0 CONTENTS, ALLOC, LOAD, READONLY, DATA 4 .comment 0000002c 0000000000000000 0000000000000000 00000067 2**0 CONTENTS, READONLY 5 .note.GNU-stack 00000000 0000000000000000 0000000000000000 00000093 2**0 CONTENTS, READONLY 6 .eh_frame 00000038 0000000000000000 0000000000000000 00000098 2**3 CONTENTS, ALLOC, LOAD, RELOC, READONLY, DATA

链接[7]

链接的过程是将一个或多个由编译器或汇编器生成的目标文件链接库(静态库或动态库)形成可执行文件。其中静态库会和汇编生成的目标文件一起链接打包到可执行文件中(静态链接),它对函数库的链接是放在编译时期完成的。而动态库在程序编译时不会被链接到可执行文件中,而是在程序运行时才会被载入(动态链接)。不同的应用程序如果调用相同的库,那么在内存中只需要一份该共享库实例。获取链接器链接后的可执行文件使用命令 gcc hello.o -o hello 。如果想看该可执行文件依赖的库,可以使用命令 ldd hello

# ldd hello 显示hello依赖的库 linux-vdso.so.1 => (0x00007ffc85980000) libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007f06c7a53000) /lib64/ld-linux-x86-64.so.2 (0x000055ad7be9e000)

参考文献

1.预处理[8]

2.预处理-行号标记[9]

3.编译器[10]

4.汇编[11]

5.链接器[12]

References

[1] hello.c: https://blog.haojunyu.com/atts/hello.c
[2] 预处理:
https://zh.wikipedia.org/wiki/C预处理器
[3] hello.i:
https://blog.haojunyu.com/atts/hello.i
[4] 编译:
https://zh.wikipedia.org/wiki/編譯器
[5] hello.s:
https://blog.haojunyu.com/atts/hello.s
[6] 汇编:
https://zh.wikipedia.org/wiki/汇编语言
[7] 链接:
https://zh.wikipedia.org/wiki/链接器
[8] 预处理:
https://zh.wikipedia.org/wiki/C预处理器
[9] 预处理-行号标记:
https://gcc.gnu.org/onlinedocs/cpp/Preprocessor-Output.html
[10] 编译器:
https://zh.wikipedia.org/wiki/編譯器
[11] 汇编:
https://zh.wikipedia.org/wiki/汇编语言
[12] 链接器:
https://zh.wikipedia.org/wiki/链接器

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌抄袭侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。

(0)
上一篇 2024年5月1日 上午11:45
下一篇 2024年5月1日 上午11:57

相关推荐

  • 陕西省科技厅科研项目公布陕西省科技厅科研项目公布

    陕西省科技厅科研项目公布 近日,陕西省科技厅发布了一系列科研项目,这些项目涉及多个领域,包括人工智能、新材料、新能源等等。这些项目旨在推动陕西省科技创新,提高创新能力,为陕西省经济…

    科研百科 2024年9月10日
    17
  • 科研项目中承担主要工作

    在科研项目中承担主要工作是一种非常重要的责任和义务,不仅能够为项目的成功做出贡献,还可以提升个人的职业能力和竞争力。本文将探讨如何在科研项目中承担主要工作,并提出一些建议。 科研项…

    科研百科 2024年10月21日
    0
  • 开票软件3.0安装初始化及数据恢复方法

    开票软件3.0的安装初始化及数据恢复方法 随着数字化时代的到来,开票软件已经成为了企业财务领域中不可或缺的一部分。开票软件3.0作为新一代的开票软件,具有更加智能化、高效化、便捷化…

    科研百科 2024年12月7日
    0
  • 研发项目经费管理

    研发项目经费管理 随着科技的不断发展,企业的研发工作也越来越重要。然而,研发项目经费管理是一个复杂而重要的任务,需要有效的预算、控制和跟踪。 在研发项目经费管理中,预算是一个非常重…

    科研百科 2024年9月12日
    22
  • 滨州市妇联2021年少儿公益夏令营开营(滨州小学生夏令营)

    滨州日报/滨州网讯 7月5日上午,滨州市妇联2021年少儿公益夏令营在市妇女儿童事业发展中心开营,60个孩子将先后在此度过一段充实、快乐的别样生活。此次活动由市妇联主办,市妇女儿童…

    科研百科 2022年8月11日
    143
  • 金丹科技2024发展战略规划

    金丹科技2024发展战略规划 近年来,随着科技的不断发展,金丹科技作为一家专注于区块链领域的企业,也面临着越来越大的挑战和机遇。为了更好地应对市场变化和客户需求,金丹科技制定了20…

    科研百科 2024年12月9日
    1
  • 创新工具助力党建,智慧党建管理平台提升工作效率,党建工作利器

    随着信息技术的快速发展,智慧党建综合管理平台应运而生。 作为党建工作的利器,智慧党建综合管理平台结合现代科技手段,旨在提高党组织管理效率、加强党员教育培训、推动党建工作创新。 本文…

    科研百科 2024年6月8日
    39
  • 德国阿福被曝上交友软件,离婚一个月就找新欢,还想约中国女生

    刚好一个月时间,在愚人节宣布离婚的德国网红阿福就被曝出上交友软件了,与此同时,他的前妻朱莉发布了视频回应了离婚风波,直言自己还爱着阿福,让迄今为止还在沉默的阿福又掉了一波粉丝。 一…

    科研百科 2024年7月25日
    57
  • 施工合同管理

    施工合同管理 施工合同管理是建筑工程管理中非常重要的一环,它涉及到建筑工程项目的施工、验收和结算等各个环节。在施工合同管理中,需要明确合同条款、合同执行和监督、合同变更和终止等关键…

    科研百科 2025年1月9日
    0
  • 科研项目负责人主要贡献科研项目负责人主要贡献

    科研项目负责人主要贡献 科研项目负责人是项目成功的关键人物之一。他们负责制定项目计划, 管理资源, 协调各个团队, 并确保项目按时完成。在这篇文章中,我们将探讨科研项目负责人的主要…

    科研百科 2024年7月10日
    55