# 一、C语言基础语法 1. **C语言结构** C语言程序源码文件以.c结尾,一个C语言程序主要包括以下部分: - 预处理指令:以'#'开头,如:#include --> 用于处理头文件 | 指令 | 说明 | | -- | -- | | `#include` | 包含(引入)一个源代码文件 | | `#define` | 定义一个宏 | | `#undef` | 取消已定义的宏 | | `#if` | 如果给定条件为真,则编译其后的代码 | | `#ifdef` | 如果宏已经定义,则编译其后的代码 | | `#ifndef` | 如果宏没有定义,则编译其后的代码 | | `#elif` | 如果前面的 `#if` 给定条件为假,并且当前条件为真,则编译其后的代码 | | `#endif` | 结束一个 `#if`、`#ifdef` 或者 `#ifndef` 条件编译块 | | `#defined` | 这不是命令,而是操作符,用来判断某个宏是否已被定义。 | - 主函数:main函数 --> C语言程序的入口,一个C语言程序有且仅有一个主函数(main) - 变量:int a,b,c;由符号(用户标识符)构成。 - 语句及表达式:语句以英文分号;结尾,if(....)表达式等等 - 注释:语句或表达式的解释,单行(`//`)和多行(`/* */`) 1. **C语言的语法** 1. C语言的令牌 在 C 语言中,令牌(Token)是程序的基本组成单位,编译器通过对源代码进行词法分析,将代码分解成一个个的令牌。C 语言的令牌主要包括以下几种类型: - 关键字(Keywords):具有特定含义的单词。 - 标识符(Identifiers):描述数据或功能的符号或单词 - 常量(Constants):数值不能修改的量 - 字符串值(String Literals):`""` - 运算符(Operators): `+、-、*、/.....` - 分隔符(Separators): `;` 1. 分号; 在C语言程序中,英文的分号是语句的结束符,每个语句必须以分号结尾,它表明一个逻辑的结束。 1. 注释 在C语言程序中,注释用于说明语句或程序的功能和使用方法,注释的语句不会参与到程序的运行只用于开发人员或 使用人员进行查阅C语言程序,注释的方式有单行(`//` )和多行(`/* */`)两种。注释不能嵌套使用。 单行注释: // 需要注释的内容 多行注释:`/* 需要注释的内容 */` 1. 标识符 在C语言中标识符用于标识变量、函数、数组等或者其他用户自定义名称或项目名字;具体要求如下 - 只能包含数字、 字母以及下划线, 不能包含其他任何特殊字符。 - 只能以大写、小写字母或者下划线开头。 - 不能跟系统已有的关键字重名, 也不能跟在相同作用域的其他标识符重名。 ```c abc(√) 123(×) _123(√) a&b(×) Ace(√) int(×) ``` 1. 关键字 在C语言程序中具有特殊功能或含义的单词,函数名、变量名、常量名及其他用户标识符不能是关键字 | 关键字 | 说明 | | ---------- | ---------------------------------- | | `auto` | 声明自动变量 | | `break` | 跳出当前循环 | | `case` | 开关语句分支 | | `char` | 声明字符型变量或函数返回值类型 | | `const` | 定义常量,如果一个变量被 const 修饰,那么它的值就不能再被改变 | | `continue` | 结束当前循环,开始下一轮循环 | | `default` | 开关语句中的"其它"分支 | | `do` | 循环语句的循环体 | | `double` | 声明双精度浮点型变量或函数返回值类型 | | `else` | 条件语句否定分支(与 if 连用) | | `enum` | 声明枚举类型 | | `extern` | 声明变量或函数是在其它文件或本文件的其他位置定义 | | `float` | 声明浮点型变量或函数返回值类型 | | `for` | 一种循环语句 | | `goto` | 无条件跳转语句 | | `if` | 条件语句 | | `int` | 声明整型变量或函数 | | `long` | 声明长整型变量或函数返回值类型 | | `register` | 声明寄存器变量 | | `return` | 子程序返回语句(可以带参数,也可不带参数) | | `short` | 声明短整型变量或函数 | | `signed` | 声明有符号类型变量或函数 | | `sizeof` | 计算数据类型或变量长度(即所占内存字节数) | | `static` | 声明静态变量 | | `struct` | 声明结构体类型 | | `switch` | 用于开关语句 | | `typedef` | 用以给数据类型取别名 | | `unsigned` | 声明无符号类型变量或函数 | | `union` | 声明共用体类型 | | `void` | 声明函数无返回值或无参数,声明无类型指针 | | `volatile` | 说明变量在程序执行中可被隐含地改变 | | `while` | 循环语句的循环条件 | ### C99 新增关键字 | `_Bool` | `_Complex` | `_Imaginary` | `inline` | `restrict` | ### C11 新增关键字 | `_Alignas` | `_Alignof` | `_Atomic` | `_Generic` | `_Noreturn` | | ---------------- | --------------- | ------- | -------- | --------- | | `_Static_assert` | `_Thread_local` | | | | # 二、编程规范 1. 命名方式 自定义标识符时要做到**见名知意** 变量名:max_number zui_da_zhi maxNumber 函数名:max_number_function ji_suan_zui_da_zhi MaxNumberFunction 常见的命名方式: - ==驼峰式== 以小写或大写字母开头,后面跟大写或小写字母,如myApp,MyName等类似的命名方式 - 匈牙利命名法 以变量类型的缩写开头,如`int iCount; unsigned int uiNum;`等 - 帕斯卡命名法 类似与驼峰式命名法,以大写字母开头,如MyApp,MyName等 - ==下划线命名法== 在Linux中最常见的命名方式,Linux一些系统库、开源软件等编码中较为常见。 如`char my_name[10];int first_num;`等 2. 缩进 在C语言源码中缩进要对齐,代码要有层级体现,最好用 8 个空格缩进,避免用 4 个空格甚至是 2 个空格 如: ```c void fun(void) { int n=10; if(n<10){ printf("...."); } } ``` 3. 空格和空行 空格和空行也是提高程序可读性的很重要的一方面,谁都不愿意阅读挤在一起的代码, 因此适当的空格和空行能让程序看起来逻辑更加清晰。 4. 括号 函数体和循环结构、分支结构等代码块需要用到花括号将其代码括起来,对于函数而言, 在 LINUX 编码风格中,左右花括号分别占用一行,在其他的代码块中,左花括号可以放在 上一行的最右边,右花括号单独占一行(推荐像函数一样左右括号各自单独占一行,使得代码的风格更具一致性)。 5. 注释 在我们编写程序的时候,如果遇到比较复杂的情形,我们可以在代码中用自然语言添加 一些内容,来辅助我们自己和将来要阅读该程序的人员更好地理解程序。 更详细的规范见《编程规范.pdf》 [编程规范.pdf](attachments/WEBRESOURCE40a76a7d230733292ec04717f3f6f254编程规范.pdf) # 三、第一个C语言程序 第一个C语言程序源码,常常是在终端中输出一段话如"Hello world" ```c #include  // <> 表示在系统的路径中寻找头文件stdio.h,未找到则报错 #include "myhead.h"  // ""表示在本目录中寻找或者在设置的路径中查找头文件,未找到则去系统路径中寻找,均未找到则报错 // 主函数,C语言程序的入口,一个完整的C语言程序必须有且只能有一个main函数 int main(int argc, char const *argv[]) {   // 函数的开始 表示函数的内容是一个整体     printf("hello GEC\n"); // 将"hello GEC\n"输出到终端屏幕     return 0;  // 函数功能的结束  不是必须的 } // 函数语句的结束 ``` 源码的第一行是#include ,#include说明它一条预处理指令,在C语言源文件编译之初就会执行执行的指令,表示告诉编译器需要加载"stdio.h"这个文件的内容到源代码中来,<>尖括号表示告诉编译器寻找这个文件的路径是优先在系统的路径中,""双引号表示告诉编译器寻找头文件的路径优先选择当前路径或明确指定的路径中进行,若未找到则去系统路径中寻找。 ![](images/WEBRESOURCE4bb07092451ff2e2b923c57cb023415dimage.png) 下一行`int main(int argc, char *argv[])`是主函数,程序执行从这里开始,自上而下进行逐一运行,C语言的程序有且仅有一个main函数,主函数的一般形式为:`int main(int argc, char *argv[])`或`int main(void)` 下一行//单行注释,编译器会自动忽略,下图一个预编译后的文件在这个文件中头文件被其内容替换,注释被删除。 ![](images/WEBRESOURCEb4c06b079d7fe90fbd6ea378458623dcimage.png) 下一行{表示代码块的开始,在C语言程序中多条语句的集合常常用花括号进行包含表示复合语句(函数体、循环体、条件语句等) 下一行`printf(....)`是C语言中另一个函数的调用,调用这个函数可以在屏幕上显示其中的内容如:Hello world,这个函数在stdio.h中声明在标准C库中定义。 下一行`return 0;`表示函数的结束,执行这个语句表示main函数的终止并返回一个0值 最后一行}表示代码块的结束 ![](images/WEBRESOURCE1ec0d881c347298235a88359695ad942image.png) 注意:如下图所示的问题是源码中缺少头文件 ![](images/WEBRESOURCE57ae4c50fdbe52495c1fec865fb6c5fbimage.png) 练习: 在终端输出自己的学校和姓名,运行结果截图发QQ群。