C: 基本语法
学C语言的基本语法就像学汉字的笔画——横竖撇捺看似简单,但所有华丽的文章都由它们组合而成。
1. 程序的基本结构
每一个C程序都有一个固定的骨架,不管程序多复杂,核心结构不变:
#include <stdio.h>
int main(void) {
return 0;
}
这是最小的合法C程序——虽然它什么都不做,但结构完整。让我们拆解每一部分:
(1) 预处理指令
#include <stdio.h> 是预处理指令,以 # 开头,在编译之前由预处理器处理。
#include—— 将指定头文件的内容插入到当前位置<stdio.h>—— 标准输入输出头文件,包含printf、scanf等函数的声明- 尖括号
<>表示在系统目录中搜索头文件
你还会遇到其他常用头文件:
| 头文件 | 提供的功能 |
|---|---|
<stdio.h> |
输入输出(printf、scanf) |
<stdlib.h> |
通用工具(malloc、exit) |
<math.h> |
数学函数(sqrt、sin) |
<string.h> |
字符串操作(strlen、strcpy) |
<ctype.h> |
字符判断(isdigit、toupper) |
(2) main函数
int main(void) {
return 0;
}
int—— 函数返回值类型为整数main—— 函数名,C语言规定程序从main函数开始执行(void)—— 参数列表为空,表示不接受任何参数{ }—— 函数体,用花括号包裹return 0—— 返回0表示程序正常结束
🔥 重要:main 是C程序唯一的入口点。一个程序只能有一个 main 函数,操作系统调用它来启动你的程序。
(3) 其他写法
你可能在某些教材中看到不同的main写法:
int main(int argc, char *argv[])
这种写法可以接收命令行参数,后续章节会详细讲解。现在用 int main(void) 就够了。
⚠️ 避免:有些老教材用 void main(),这不是标准C写法,某些编译器会发出警告。始终使用 int main(void)。
2. 语句与分号
C语言中,分号 ; 是语句的结束标志。这和中文的句号类似——一句话说完要加句号,一条语句写完要加分号。
int age = 18;
age = age + 1;
printf("I am %d years old\n", age);
每一行都是一条语句,以分号结尾。
常见错误——忘记分号:
int age = 18
编译器不认"换行",只认分号。所以理论上你可以把所有代码写在一行:
int age = 18; age = age + 1; printf("%d\n", age);
虽然语法合法,但绝不推荐这样写。良好的代码风格是一条语句占一行。
💡 空语句:单独一个分号也是合法语句,称为空语句,什么都不做:
;
它在某些特殊场景下有用(如空循环体),但现在不需要关心。
3. 代码块
花括号 {} 包裹的一组语句构成一个代码块(也叫复合语句):
int main(void) {
int x = 10;
int y = 20;
int sum = x + y;
printf("Sum = %d\n", sum);
return 0;
}
整个 main 函数体就是一个代码块。代码块定义了作用域——在块内声明的变量,块外无法访问。
代码块可以嵌套:
int main(void) {
int a = 1;
{
int b = 2;
printf("a + b = %d\n", a + b);
}
return 0;
}
内层代码块可以访问外层的 a,但外层无法访问内层的 b。
⚠️ 风格建议:即使代码块只有一条语句,也建议写花括号。这能避免后续添加语句时忘记加花括号的bug。
4. printf函数
printf 是C语言最常用的输出函数,名字来自 print formatted(格式化打印)。
(1) 基本用法
printf("Hello, World!\n");
双引号内的内容称为格式字符串,会原样输出(转义字符除外)。
(2) 格式占位符
printf 的强大之处在于格式化输出变量的值:
int age = 18;
float height = 1.75f;
char grade = 'A';
printf("Age: %d\n", age);
printf("Height: %.2f\n", height);
printf("Grade: %c\n", grade);
常用占位符:
| 占位符 | 对应类型 | 示例输出 |
|---|---|---|
%d |
int | 42 |
%f |
float / double | 3.140000 |
%.2f |
float(保留2位小数) | 3.14 |
%c |
char | A |
%s |
字符串 | hello |
%ld |
long | 100000 |
%x |
十六进制整数 | 2a |
%o |
八进制整数 | 52 |
%% |
输出百分号本身 | % |
💡 多个占位符:可以在一个 printf 中使用多个占位符,按顺序对应后面的参数:
int a = 3, b = 4;
printf("%d + %d = %d\n", a, b, a + b);
(3) 宽度与对齐
printf("[%5d]\n", 42);
printf("[%-5d]\n", 42);
printf("[%05d]\n", 42);
[ 42]
[42 ]
[00042]
%5d—— 最小宽度5,右对齐%-5d—— 最小宽度5,左对齐%05d—— 最小宽度5,用0填充
5. 转义字符
在字符串中,有些字符无法直接输入(如换行、制表符),需要用转义字符表示。转义字符以反斜杠 \ 开头:
| 转义字符 | 含义 | 示例 |
|---|---|---|
\n |
换行 | printf("A\nB") 输出A和B各占一行 |
\t |
水平制表符 | 对齐输出时常用 |
\\ |
反斜杠本身 | 输出 \ 需要写 \\ |
\" |
双引号 | 在字符串中输出 " |
\' |
单引号 | 在字符中输出 ' |
\0 |
空字符 | 字符串结束标志 |
\r |
回车 | 光标回到行首 |
\b |
退格 | 光标左移一格 |
⚠️ 易错点:输出路径时必须用双反斜杠:
printf("C:\\Users\\admin\\file.txt\n");
C:\Users\admin\file.txt
6. 注释
注释是写给人看的说明文字,编译器会完全忽略。好的注释能让代码更容易理解。
(1) 单行注释
C99引入了 // 风格的单行注释,从 // 到行末的内容都是注释:
int score = 100;
(2) 多行注释
/* */ 风格的注释可以跨越多行:
/*
* This program calculates
* the sum of two numbers
*/
#include <stdio.h>
int main(void) {
int a = 10;
int b = 20;
printf("%d\n", a + b);
return 0;
}
(3) 注释的最佳实践
注释应该解释为什么(Why),而不是是什么(What)。代码本身已经说明了What,注释要补充的是代码无法表达的设计意图和决策原因。
好的注释:
int max_retries = 3;
不必要的注释(代码已经说明了一切):
int x = 10;
⚠️ 注意:多行注释不能嵌套。以下写法会导致编译错误:
/*
/* nested comment */
*/
内层的 */ 会提前结束外层注释,导致后面的 */ 成为语法错误。
7. 标识符与关键字
(1) 标识符命名规则
标识符就是你自己起的名字(变量名、函数名等),必须遵循:
- 只能包含字母(a-z, A-Z)、数字(0-9)和下划线(_)
- 必须以字母或下划线开头,不能以数字开头
- 区分大小写(
age和Age是两个不同的标识符) - 不能使用C语言的关键字
合法命名:age、student_name、_count、MAX_SIZE
非法命名:2name(数字开头)、my-age(含减号)、int(关键字)
(2) 命名风格
| 风格 | 格式 | 适用场景 | 示例 |
|---|---|---|---|
| snake_case | 小写+下划线 | 变量名、函数名 | student_count |
| UPPER_CASE | 全大写+下划线 | 常量名 | MAX_BUFFER_SIZE |
| CamelCase | 首字母大写 | 自定义类型名 | StudentInfo |
C语言传统上使用 snake_case 风格,这与Java/C#的camelCase风格不同。保持项目内风格统一最重要。
(3) C99关键字
C99共有37个关键字,全部为小写:
| 类别 | 关键字 |
|---|---|
| 数据类型 | char short int long float double void signed unsigned _Bool _Complex _Imaginary |
| 控制语句 | if else switch case default for while do break continue goto return |
| 存储类 | auto extern static register typedef inline |
| 结构 | struct union enum |
| 其他 | const volatile sizeof restrict |
这些关键字不需要背,写多了自然就记住了。重要的是知道关键字不能作为标识符使用。
▶ 示例
综合运用本节所学知识,写一个展示基本语法的程序:
#include <stdio.h>
int main(void) {
printf("=== Student Info ===\n");
printf("Name:\t%s\n", "Zhang San");
printf("Age:\t%d\n", 20);
printf("Score:\t%.1f\n", 95.5);
printf("Grade:\t%c\n", 'A');
printf("====================\n");
return 0;
}
=== Student Info ===
Name: Zhang San
Age: 20
Score: 95.5
Grade: A
====================
这个程序展示了:#include 预处理指令、main 函数结构、printf 格式化输出、\n 换行、\t 制表符对齐,以及 %d、%.1f、%c、%s 四种常用占位符。
❓ 常见问题
📖 小节
- C程序的基本骨架:
#include头文件 +int main(void)函数 +return 0 - 分号是语句的结束标志,每条语句必须以分号结尾
- 花括号
{}构成代码块,定义变量的作用域 - printf 用格式占位符输出不同类型的数据:
%d、%f、%c、%s - 转义字符以
\开头,\n换行、\t制表、\\输出反斜杠
📝 作业
- 编写程序,用printf输出一个你自己的信息卡片(姓名、年龄、爱好),使用\t对齐
- 编写程序,用一次printf调用输出以下内容(使用转义字符实现换行和制表):姓名 张三、年龄 25、城市 北京
- 故意在代码中写一个多行注释嵌套的例子,观察编译器的报错信息