C语言程序的编译与预处理基础定义讲解
什么是编译过程
编译是指将高级语言(C语言)源代码转换成可执行代码的过程。编译过程涉及到预处理、编译、汇编和链接等多个步骤。
预处理阶段
预处理阶段的主要任务是根据预处理指令将源代码进行处理,然后输出修改后的源代码作为下一步的编译输入。预处理指令以“#”开头,常用的指令有:
- include:将指定的头文件内容插入到当前文件中;
- define:用于定义宏;
- ifdef、ifndef、endif:用于条件编译等。
假设有一个文件“test.c”:
#include <stdio.h>
#define MAX_LEN 100
int main() {
char buffer[MAX_LEN] = "hello world";
printf("%s\n", buffer);
return 0;
}
使用以下命令可以将该程序进行预处理:
gcc -E test.c -o test.i
预处理后的文件“test.i”内容如下:
# 1 "test.c"
# 1 "<built-in>"
# 1 "<command-line>"
# 1 "test.c"
# 1 "/usr/include/stdio.h" 1 3 4
# 27 "/usr/include/stdio.h" 3 4
...
#define MAX_LEN 100
int main() {
char buffer[MAX_LEN] = "hello world";
printf("%s\n", buffer);
return 0;
}
可以发现,预处理后的文件已经将“stdio.h”中包含的内容插入到了当前文件中,并且将宏定义“MAX_LEN”展开。预处理的结果是一个包含完整头文件内容和宏定义展开的新文件。
编译阶段
编译阶段的主要任务是将预处理输的代码转换成汇编语言代码。在编译过程中会进行语法分析和语义分析,语法分析检查程序的语法是否正确,语义分析检查程序的语义是否正确。
假设预处理后的文件“test.i”已经存在,使用以下命令将其编译成汇编语言代码:
gcc -S test.i -o test.s
编译后的文件“test.s”内容如下:
.file "test.c"
.text
.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
subq $112, %rsp
movl $100, -104(%rbp)
leaq -104(%rbp), %rax
movq %rax, %rdi
movl $0, %eax
call strcpy@PLT
leaq .LC0(%rip), %rax
movq %rax, %rsi
leaq -104(%rbp), %rax
movq %rax, %rdi
movl $0, %eax
call printf@PLT
movl $0, %eax
leave
.cfi_def_cfa 7, 8
ret
.cfi_endproc
.LFE0:
.size main, .-main
.ident "GCC: (Ubuntu 9.3.0-10ubuntu2) 9.3.0"
.section .note.GNU-stack,"",@progbits
可以看到,编译后的文件已经转换成了汇编语言代码。
汇编阶段和链接阶段
汇编阶段和链接阶段主要是将汇编代码转换成可执行代码。汇编阶段使用汇编器将汇编代码转换成机器代码,链接阶段使用链接器将汇编产生的目标文件和库文件链接成可执行文件。
假设已经存在汇编代码文件“test.s”,使用以下命令将其转换成可执行文件:
gcc test.s -o test
至此,编译过程已经完成,生成了一个文件名为“test”的可执行文件。
示例
下面使用一个简单的示例来说明编译过程:
#include <stdio.h>
#define MAX(a, b) (a > b ? a : b)
int main() {
int num1 = 10;
int num2 = 20;
printf("max=%d\n", MAX(num1, num2));
return 0;
}
使用以下命令进行编译:
gcc test.c -o test
可以看到,在编译过程中会报错:
test.c: In function ‘main’:
test.c:8:5: error: expected ‘;’ before ‘return’
return 0;
^
这是因为在使用宏定义“MAX(a, b)”时没有加括号,导致编译器将预处理结果认为是一个语句,因此需要在宏定义的代码周围加上括号,修改后的代码如下:
#include <stdio.h>
#define MAX(a, b) (a > b ? a : b)
int main() {
int num1 = 10;
int num2 = 20;
printf("max=%d\n", MAX(num1, num2));
return 0;
}
重新编译即可成功生成可执行文件。
本站文章如无特殊说明,均为本站原创,如若转载,请注明出处:C语言程序的编译与预处理基础定义讲解 - Python技术站