C 语言基础语法
1. C 语言是什么
C 语言是一门经典的编程语言,特点是:
- 运行效率高
- 接近底层
- 语法简洁
- 适合学习程序设计基础
- 广泛用于操作系统、嵌入式、驱动、编译器等领域
很多现代语言都受 C 语言影响。
2. 第一个 C 程序
c
#include <stdio.h>
int main(void)
{
printf("Hello, C!\n");
return 0;
}输出:
text
Hello, C!3. #include <stdio.h>
c
#include <stdio.h>表示引入标准输入输出库。
因为:
c
printf()
scanf()这些函数都定义在:
text
stdio.h中。
4. main 函数
C 程序通常从:
c
main()函数开始执行。
标准写法:
c
int main(void)
{
return 0;
}其中:
text
int表示 main 最终返回一个整数。
c
return 0;通常表示程序正常结束。
5. C 语言使用分号
C 语言中的大多数语句结尾需要:
text
;例如:
c
int age = 18;
printf("%d\n", age);如果忘记写分号,通常会编译报错。
6. 注释
单行注释:
c
// 这是单行注释多行注释:
c
/*
这是
多行注释
*/例如:
c
int age = 18; // 用户年龄变量
7. 什么是变量
变量用于保存数据。
例如:
c
int age = 18;这里:
text
int是数据类型。
text
age是变量名。
text
18是变量的值。
8. C 语言变量必须先声明类型
Python 可以:
python
age = 18而 C 语言通常必须写:
c
int age = 18;因为 C 是静态类型语言。
9. 常见基本数据类型
| 类型 | 含义 | 示例 |
|---|---|---|
char | 字符 | 'A' |
int | 整数 | 100 |
float | 单精度浮点数 | 3.14f |
double | 双精度浮点数 | 3.14 |
例如:
c
char grade = 'A';
int age = 18;
float height = 1.75f;
double pi = 3.1415926;10. char
char 用于保存单个字符。
例如:
c
char ch = 'A';注意字符使用:
text
单引号例如:
c
'A'而:
c
"A"是字符串,不是单个字符。
11. int
int 用于保存整数。
例如:
c
int age = 18;
int score = 100;
int number = -10;12. float
c
float price = 19.99f;通常建议在浮点常量后写:
text
f表示这是 float。
13. double
c
double pi = 3.1415926535;double 通常比 float 精度更高。
14. sizeof
可以使用:
c
sizeof查看类型或变量占多少字节。
例如:
c
printf("%zu\n", sizeof(int));也可以:
c
int age = 18;
printf("%zu\n", sizeof(age));不同平台的具体大小可能有所差异。
输出
15. printf
C 语言最常用的输出函数:
c
printf()例如:
c
printf("Hello\n");16. 格式化输出
输出整数:
c
int age = 18;
printf("%d\n", age);其中:
text
%d表示输出十进制整数。
17. 常见格式说明符
| 格式 | 用途 |
|---|---|
%d | int |
%c | char |
%f | 浮点数 |
%s | 字符串 |
%u | 无符号整数 |
%ld | long |
%p | 地址 |
例如:
c
char grade = 'A';
int age = 18;
double height = 1.75;
printf("%c\n", grade);
printf("%d\n", age);
printf("%f\n", height);18. 一次输出多个变量
c
int age = 18;
double height = 1.75;
printf("age = %d, height = %.2f\n", age, height);其中:
text
%.2f表示保留两位小数。
19. 转义字符
常见:
| 转义字符 | 作用 |
|---|---|
\n | 换行 |
\t | 制表符 |
\" | 双引号 |
\\ | 反斜杠 |
例如:
c
printf("Hello\nWorld\n");输出:
text
Hello
World输入
20. scanf
C 语言常用:
c
scanf()获取输入。
例如:
c
int age;
scanf("%d", &age);输入:
text
18那么:
text
age就会保存:
text
1821. 为什么 scanf 里有 &
例如:
c
scanf("%d", &age);这里:
text
&age表示:
text
age 的内存地址scanf 需要知道把输入的数据写到哪里,所以需要变量地址。
这是 C 语言中指针概念的基础。
22. 输入多个值
c
int a;
int b;
scanf("%d %d", &a, &b);例如输入:
text
10 20那么:
text
a = 10
b = 20常量
23. const
如果变量初始化之后不希望修改:
c
const int MAX = 100;之后不能正常写:
c
MAX = 200;24. 宏常量
也可以:
c
#define PI 3.1415926例如:
c
#include <stdio.h>
#define PI 3.1415926
int main(void)
{
printf("%f\n", PI);
return 0;
}运算符
25. 算术运算符
| 运算符 | 含义 |
|---|---|
+ | 加 |
- | 减 |
* | 乘 |
/ | 除 |
% | 取余 |
例如:
c
int a = 10;
int b = 3;
printf("%d\n", a + b);
printf("%d\n", a - b);
printf("%d\n", a * b);
printf("%d\n", a / b);
printf("%d\n", a % b);26. 整数除法
如果两个操作数都是整数:
c
int a = 10;
int b = 3;
printf("%d\n", a / b);输出:
text
3小数部分会被丢弃。
27. 浮点除法
如果希望得到:
text
3.333...可以:
c
double result = 10.0 / 3.0;或者:
c
double result = (double)10 / 3;28. 取余 %
c
int result = 10 % 3;结果:
text
1常用于:
text
判断奇偶
循环处理
取个位数例如判断偶数:
c
if (number % 2 == 0)
{
printf("偶数\n");
}29. 自增和自减
c
i++;表示:
c
i = i + 1;自减:
c
i--;表示:
c
i = i - 1;比较运算
30. 比较运算符
| 运算符 | 含义 |
|---|---|
== | 等于 |
!= | 不等于 |
> | 大于 |
< | 小于 |
>= | 大于等于 |
<= | 小于等于 |
例如:
c
int age = 18;
printf("%d\n", age >= 18);条件成立时通常得到:
text
1不成立通常得到:
text
031. = 和 ==
一定不要混淆。
c
a = 10;表示:
text
赋值而:
c
a == 10表示:
text
判断是否相等逻辑运算
32. 逻辑运算符
| 运算符 | 含义 |
|---|---|
&& | 与 |
| ` | |
! | 非 |
例如:
c
if (age >= 18 && age <= 60)
{
printf("满足条件\n");
}33. &&
两个条件都成立:
c
a > 0 && b > 0结果才成立。
34. ||
只要有一个条件成立:
c
a > 0 || b > 0结果就成立。
35. !
取反:
c
!condition例如:
c
if (!is_ok)
{
printf("条件不成立\n");
}条件判断
36. if
基本结构:
c
if (条件)
{
代码;
}例如:
c
int age = 20;
if (age >= 18)
{
printf("成年人\n");
}37. if...else
c
if (age >= 18)
{
printf("成年人\n");
}
else
{
printf("未成年人\n");
}38. if...else if...else
c
int score = 85;
if (score >= 90)
{
printf("优秀\n");
}
else if (score >= 80)
{
printf("良好\n");
}
else if (score >= 60)
{
printf("及格\n");
}
else
{
printf("不及格\n");
}39. 花括号
C 语言使用:
text
{}表示代码块。
例如:
c
if (age >= 18)
{
printf("成年人\n");
printf("条件成立\n");
}switch
40. switch
当一个变量需要和多个固定值比较时,可以使用:
c
switch例如:
c
int choice = 2;
switch (choice)
{
case 1:
printf("选项 1\n");
break;
case 2:
printf("选项 2\n");
break;
case 3:
printf("选项 3\n");
break;
default:
printf("无效选项\n");
}41. break
在 switch 中:
c
break;用于结束当前分支。
如果忘记:
c
break;程序可能继续执行后面的 case。
循环
42. for 循环
基本结构:
c
for (初始化; 条件; 更新)
{
代码;
}例如:
c
for (int i = 0; i < 5; i++)
{
printf("%d\n", i);
}输出:
text
0
1
2
3
443. for 的执行过程
c
for (int i = 0; i < 5; i++)可以拆成:
text
1. int i = 0
2. 判断 i < 5
3. 执行循环体
4. i++
5. 再判断 i < 5不断重复。
44. while
基本结构:
c
while (条件)
{
代码;
}例如:
c
int i = 0;
while (i < 5)
{
printf("%d\n", i);
i++;
}45. do...while
c
do
{
代码;
}
while (条件);例如:
c
int i = 0;
do
{
printf("%d\n", i);
i++;
}
while (i < 5);特点:
text
循环体至少执行一次46. break
break 可以提前退出循环。
例如:
c
for (int i = 0; i < 10; i++)
{
if (i == 5)
{
break;
}
printf("%d\n", i);
}输出:
text
0
1
2
3
447. continue
continue 跳过本次循环剩余代码。
例如:
c
for (int i = 0; i < 5; i++)
{
if (i == 2)
{
continue;
}
printf("%d\n", i);
}输出:
text
0
1
3
4数组
48. 一维数组
数组可以保存多个相同类型的数据。
例如:
c
int numbers[5] = {10, 20, 30, 40, 50};数组长度:
text
549. 数组下标
C 数组下标从:
text
0开始。
例如:
text
numbers[0] = 10
numbers[1] = 20
numbers[2] = 30访问:
c
printf("%d\n", numbers[0]);50. 修改数组元素
c
numbers[0] = 100;修改后:
text
第一个元素变成 10051. 遍历数组
c
int numbers[5] = {10, 20, 30, 40, 50};
for (int i = 0; i < 5; i++)
{
printf("%d\n", numbers[i]);
}52. 计算数组长度
可以:
c
int numbers[] = {10, 20, 30, 40, 50};
int length = sizeof(numbers) / sizeof(numbers[0]);结果:
text
5常见写法:
c
for (int i = 0; i < sizeof(numbers) / sizeof(numbers[0]); i++)
{
printf("%d\n", numbers[i]);
}字符串
53. C 语言字符串
C 语言没有独立的基础字符串类型。
字符串本质上是:
text
char 数组例如:
c
char name[] = "Tom";实际类似:
text
'T' 'o' 'm' '\0'最后会有:
text
\0表示字符串结束。
54. 输出字符串
c
char name[] = "Tom";
printf("%s\n", name);其中:
text
%s表示字符串。
55. 字符串和字符
字符:
c
char ch = 'A';使用:
text
单引号字符串:
c
char text[] = "A";使用:
text
双引号二者完全不同。
56. string.h
处理字符串时经常需要:
c
#include <string.h>常见函数:
text
strlen
strcmp
strcpy
strcat57. strlen
获取字符串长度:
c
#include <stdio.h>
#include <string.h>
int main(void)
{
char text[] = "Hello";
printf("%zu\n", strlen(text));
return 0;
}输出:
text
558. strcmp
比较两个字符串:
c
strcmp(a, b)不能直接用:
c
a == b比较字符串内容。
例如:
c
if (strcmp(name, "Tom") == 0)
{
printf("相等\n");
}函数
59. 定义函数
例如:
c
void hello(void)
{
printf("Hello\n");
}调用:
c
hello();60. 带参数的函数
c
void hello(char name[])
{
printf("Hello, %s\n", name);
}调用:
c
hello("Tom");61. 有返回值的函数
c
int add(int a, int b)
{
return a + b;
}调用:
c
int result = add(10, 20);
printf("%d\n", result);输出:
text
3062. 函数声明
如果函数定义写在 main 后面,通常需要提前声明。
例如:
c
#include <stdio.h>
int add(int a, int b);
int main(void)
{
int result = add(10, 20);
printf("%d\n", result);
return 0;
}
int add(int a, int b)
{
return a + b;
}这里:
c
int add(int a, int b);就是函数声明。
作用域
63. 局部变量
函数内部声明的变量通常是局部变量。
例如:
c
void test(void)
{
int number = 10;
}number 通常只能在:
text
test函数内部使用。
64. 全局变量
定义在函数外:
c
int number = 10;
int main(void)
{
printf("%d\n", number);
return 0;
}这样的变量属于:
text
全局变量一般不建议无节制使用全局变量。
指针基础
65. 地址
每个变量在内存中都有一个地址。
例如:
c
int number = 10;可以:
c
printf("%p\n", (void *)&number);其中:
text
&表示:
text
取地址66. 指针
指针是:
text
保存内存地址的变量例如:
c
int number = 10;
int *p = &number;这里:
text
p保存:
text
number 的地址67. * 解引用
c
printf("%d\n", *p);表示:
text
访问 p 指向地址中的值输出:
text
10可以简单记:
text
&变量
获取地址
*指针
访问这个地址里的值68. 修改指针指向的数据
c
int number = 10;
int *p = &number;
*p = 20;此时:
text
number也变成:
text
20结构体
69. struct
结构体可以把多个不同类型的数据组合起来。
例如:
c
struct Student
{
char name[20];
int age;
double score;
};创建变量:
c
struct Student student;70. 访问结构体成员
c
student.age = 18;
student.score = 90.5;使用:
text
.访问成员。
例如:
c
printf("%d\n", student.age);71. 初始化结构体
c
struct Student
{
char name[20];
int age;
};
int main(void)
{
struct Student student = {"Tom", 18};
printf("%s %d\n", student.name, student.age);
return 0;
}类型转换
72. 自动类型转换
例如:
c
int a = 10;
double b = a;C 会自动把:
text
10转换为:
text
10.073. 强制类型转换
格式:
c
(类型)变量例如:
c
int a = 10;
int b = 3;
double result = (double)a / b;结果:
text
3.333...枚举
74. enum
枚举可以给一组整数常量起名字。
例如:
c
enum Day
{
MONDAY,
TUESDAY,
WEDNESDAY
};默认:
text
MONDAY = 0
TUESDAY = 1
WEDNESDAY = 2typedef
75. 类型别名
例如:
c
typedef unsigned int uint;以后可以:
c
uint age = 18;76. 结构体配合 typedef
常见写法:
c
typedef struct
{
char name[20];
int age;
} Student;之后:
c
Student student;不需要每次都写:
c
struct Student文件基本结构
77. 一个普通 C 程序
c
#include <stdio.h>
int add(int a, int b);
int main(void)
{
int a = 10;
int b = 20;
int result = add(a, b);
printf("%d\n", result);
return 0;
}
int add(int a, int b)
{
return a + b;
}可以看到:
text
头文件
函数声明
main 函数
其他函数编译和运行
78. C 代码需要编译
Python 可以直接:
bash
python main.pyC 通常需要先:
text
源代码
↓
编译器
↓
可执行文件79. 使用 GCC 编译
假设文件:
text
main.c编译:
bash
gcc main.c -o main运行:
bash
./main80. 使用 Clang 编译
macOS 常见:
bash
clang main.c -o main然后:
bash
./main81. 推荐打开警告
学习 C 时推荐:
bash
gcc -Wall -Wextra main.c -o main或者:
bash
clang -Wall -Wextra main.c -o main这样编译器会帮你发现更多潜在问题。
常见基础练习
82. 判断奇偶数
c
#include <stdio.h>
int main(void)
{
int number;
scanf("%d", &number);
if (number % 2 == 0)
{
printf("偶数\n");
}
else
{
printf("奇数\n");
}
return 0;
}83. 求 1 到 100 的和
c
#include <stdio.h>
int main(void)
{
int sum = 0;
for (int i = 1; i <= 100; i++)
{
sum += i;
}
printf("%d\n", sum);
return 0;
}84. 找最大值
c
#include <stdio.h>
int main(void)
{
int a;
int b;
scanf("%d %d", &a, &b);
if (a > b)
{
printf("%d\n", a);
}
else
{
printf("%d\n", b);
}
return 0;
}85. 最大公约数
使用辗转相除法:
c
#include <stdio.h>
int main(void)
{
int a;
int b;
scanf("%d %d", &a, &b);
while (b != 0)
{
int temp = a % b;
a = b;
b = temp;
}
printf("%d\n", a);
return 0;
}86. 冒泡排序
c
#include <stdio.h>
int main(void)
{
int numbers[] = {5, 3, 8, 1, 2};
int length = sizeof(numbers) / sizeof(numbers[0]);
for (int i = 0; i < length - 1; i++)
{
for (int j = 0; j < length - 1 - i; j++)
{
if (numbers[j] > numbers[j + 1])
{
int temp = numbers[j];
numbers[j] = numbers[j + 1];
numbers[j + 1] = temp;
}
}
}
for (int i = 0; i < length; i++)
{
printf("%d ", numbers[i]);
}
printf("\n");
return 0;
}易错点
87. = 和 ==
错误:
c
if (a = 10)这表示赋值。
判断相等应该写:
c
if (a == 10)88. 数组越界
例如:
c
int numbers[5];合法下标:
text
0
1
2
3
4访问:
c
numbers[5]属于越界。
C 语言通常不会自动帮你检查数组边界,所以要特别小心。
89. 未初始化变量
例如:
c
int number;
printf("%d\n", number);number 没有初始化,它的值是不确定的。
更推荐:
c
int number = 0;90. 整数除法
c
int result = 5 / 2;结果:
text
2不是:
text
2.5如果需要小数:
c
double result = 5.0 / 2;91. 字符串不能直接用 ==
例如:
c
char name[] = "Tom";不要用:
c
name == "Tom"比较字符串内容。
应该使用:
c
strcmp(name, "Tom") == 092. scanf 忘记 &
整数输入:
c
scanf("%d", &age);而不是:
c
scanf("%d", age);因为 scanf 需要变量地址。
93. % 只能用于整数
例如:
c
10 % 3可以。
但是普通 % 运算符不能直接用于浮点数。
基础语法速查
94. 变量
c
int age = 18;
double height = 1.75;
char grade = 'A';95. 输出
c
printf("%d\n", age);96. 输入
c
scanf("%d", &age);97. 判断
c
if (age >= 18)
{
printf("成年人\n");
}
else
{
printf("未成年人\n");
}98. for
c
for (int i = 0; i < 10; i++)
{
printf("%d\n", i);
}99. while
c
while (condition)
{
// ...
}100. 数组
c
int numbers[] = {1, 2, 3, 4, 5};101. 字符串
c
char text[] = "Hello";102. 函数
c
int add(int a, int b)
{
return a + b;
}103. 指针
c
int number = 10;
int *p = &number;知识结构
104. C 语言基础学习顺序
建议按照下面的顺序学习:
text
C 语言基础
├── 程序结构
├── 变量与数据类型
├── 输入输出
├── 运算符
├── if / switch
├── for / while
├── 数组
├── 字符串
├── 函数
├── 指针
├── 结构体
└── 文件操作其中最重要的基础部分是:
text
变量
判断
循环
数组
函数
指针小结
C 语言最基础的程序结构:
c
#include <stdio.h>
int main(void)
{
printf("Hello, C!\n");
return 0;
}入门阶段最需要掌握:
text
变量与数据类型
printf / scanf
运算符
if / else
switch
for / while
数组
字符串
函数之后重点进入 C 语言真正核心的内容:
text
指针
数组与指针
字符串与指针
结构体
动态内存
文件操作其中尤其重要的是:
text
数组从 0 开始
= 是赋值
== 是比较
scanf 通常需要变量地址
整数 / 整数仍然是整数除法
字符串本质上是 char 数组
指针保存的是内存地址把这些基础语法真正写熟之后,再学习指针和内存管理会容易很多。