每个 C 程序都必须有一个 main
函数,是因为 main
函数是一个程序执行的起点,如下所示。
// main.c
#include <stdio.h>
int main() {
/*
创建指向字符的指针来指向字符串常量,并在控制台输出
*/
char *str = "Hello World!";
// 输出字符串常量 str
printf("%sn", str);
return 0;
}
编译
如上所示,上面的 main.c
程序通过编译过程转换为目标代码,然后,各个目标文件由链接器链接在一起,形成单一而完整的可执行程序。如使用 gcc
编译器编译 main.c
程序,并把它翻译成一个可执行目标文件 main
gcc -o main main.c
上述翻译过程可分为四个阶段,如下图所示。执行这四个阶段的程序一起构成了编译系统。
-
预处理阶段。预处理器在源代码中执行一些文本操作。如 #define
定义的宏或读入#include
指令包含的文件内容。 -
编译阶段。编译器将经过预处理之后的程序转换成特定汇编代码的过程。 -
汇编阶段。汇编器将汇编代码翻译成机器语言指令,并把这些指令打包并保存到目标文件,是二进制格式。 -
链接阶段。链接器将多个目标文件以及所需的库文件链接成最终的可执行文件,可以被加载到内存中,由系统执行。
词法规则
一个 C 程序由声明和函数组成。函数定义需要执行的工作,声明描述函数和函数将要操作的数据类型。注释散布于源文件的各个地方。
字符
标准并没有规定 C 环境必须使用哪种特定字符集,但规定字符集必须包含大写字母 A~Z
、小写字母 a~z
、数字 0~9
以及下面这些符号:
! " # % ' ( ) * + , - . / :
; < > = ? [ ] ^ _ { } | ~
除此之外,还有空白字符,如换行符 n
、退格符 b
、回车符 r
、水平制表符 t
、垂直制表符 v
等等。
注释
C 语言提供了两种注释方式。
-
以符号 /*
开始,到符号*/
结束的注释。中间包含除*/
之外的任何字符均作为注释的内容。可跨越多行,但不能嵌套于另一个注释中。 -
以符号 //
开始,//
之后的内容均作为注释的内容,只标注单行,不能跨越多行注释。
/*
创建指向字符的指针来指向字符串常量,并在控制台输出
*/
如上所示,被 /**/
包围的内容为注释内容,想使用单行注释,就使用 //
。
// 输出字符串常量
标识符
标识符 identifier
是变量、函数、类型等的名字,由大小写字母、数字和下划线组成,但不能以数字开头,并且 C 语言是一种大小写敏感的语言,所以要区分大小写。
abc_123 // 正确
_abc123 // 正确
123_abc // 错误
标识符的长度没有限制,但标准允许编译器忽略第 31
个字符以后的字符。标准同时允许编译器对由链接器操纵的名字的标识符进行限制,只识别前六位不区分大小写的字符。
在 C 语言中,被保留的关键字不能作为标识符使用。
char | short | int | unsigned | signed | long | float | double |
---|---|---|---|---|---|---|---|
struct | union | void | enum | const | volatile | typedef | auto |
register | static | extern | break | case | continue | default | do |
else | for | goto | if | return | switch | while | sizeof |
以下是C99新增关键字 |
|||||||
_Bool | _Complex | _Imaginary | inline | restrict | |||
以下是C11新增关键字 | |||||||
_Alignas | _Alignof | _Atomic | _Generic | _Noreturn | _Static_assert | _Thread_local |
原文始发于微信公众号(海人为记):一文讲解C语言编译过程
版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。
文章由半码博客整理,本文链接:https://www.bmabk.com/index.php/post/27451.html