本文最后更新于 2025-03-11,学习久了要注意休息哟

第一章 C语言入门基础

1.1 开发环境搭建

1.1.1 gcc 安装

1.1.2 gdb安装

1.1.3 vscode安装

1.2 基本语法元素

📌 核心三要素

1、关键字

  • C语言预定义的32个保留字(不可用作标识符)
  • 常用关键字速查表
    auto     break    case     char     const  
    continue default  do       double   else  
    enum     extern   float    for      goto  
    if       int      long     register return  
    short    signed   sizeof   static   struct  
    switch   typedef  union    unsigned void  
    volatile while  
    
  • ⚠️ 易混点
    • sizeof 是运算符,不是函数
    • const 定义的是只读变量,非常量

2、标识符

  • 命名规则
    • 由字母/数字/下划线组成
    • 不能以数字开头(如 2num 非法)
    • 区分大小写(sumSum 不同)
  • 行业规范
    类型命名风格示例
    变量小驼峰studentAge
    常量全大写+下划线MAX_SIZE
    函数动词+名词calculateSum

3、注释

  • 单行注释// 注释内容
    int sum = 0;  // 初始化累加器  
    
  • 多行注释/* 注释内容 */
    /*  
     * 函数:计算阶乘  
     * 参数:n - 输入整数  
     */  
    
  • ⚠️ 注释规范
    • 禁止嵌套多行注释(/* /* 内层 */ */ 错误)
    • 重要算法必须添加注释
    • 避免无意义的注释(如 i++; // i加1

4、分号

  • 语句终止符:所有表达式语句必须以 ; 结尾
  • 常见错误
    if(a > b);  // ❌ 空语句导致逻辑错误  
    {  
        printf("a更大");  
    }  
    

1.3 输入输出基础

🖨️ 输出函数

1、printf() 格式输出

基本格式

printf("格式字符串", 参数列表);  

格式说明符

格式符说明示例输出结果
%d十进制整数printf("%d", 25)25
%f浮点数(默认6位小数)printf("%f", 3.14)3.140000
%c单个字符printf("%c", 'A')A
%s字符串printf("%s", "Hello")Hello
%p指针地址printf("%p", &a)0x7ffe3b

格式控制进阶

printf("%-8d", 100);   // 左对齐,占8位 → "100     "  
printf("%08d", 100);   // 补前导0 → "00000100"  
printf("%.2f", 3.1415); // 保留2位小数 → "3.14"  

转义字符

转义符功能示例
\n换行printf("Hello\nWorld");
\t水平制表符printf("Name:\tJohn");
\\输出反斜杠printf("路径:C:\\");
%%输出百分号printf("占比:%d%%", 80);

2、字符/ 字符串输出

// 头文件
#include <stdio.h>

// 输出字符到文件
int fputc(int c, FILE *stream);
// 输出字符串到文件
int fputs(const char *s, FILE *stream);
// 输出字符到文件
int putc(int c, FILE *stream);
// 输出字符到终端
int putchar(int c);
// 输出字符串到终端
int puts(const char *s);

⌨️ 输入函数

1、scanf() 格式输入

基本用法

int age;  
scanf("%d", &age);  // 必须用&获取变量地址  

多数据输入

float height, weight;
scanf("%f%f", &height, &weight);  // 输入用空格分隔

缓冲区问题

char ch;  
scanf("%c", &ch);  // 可能读取到上次输入的换行符  
// 解决方案:  
scanf(" %c", &ch); // 添加空格跳过空白字符  

输入验证

int num;  
while(1){  
    printf("输入1-100的数:");  
    if(scanf("%d", &num) == 1 && num>=1 && num<=100){  
        break;  
    }  
    while(getchar() != '\n');  // 清空输入缓冲区  
}  

2、字符/字符串输入

// 头文件
#include <stdio.h>

// 从文件中获取一个字符
int fgetc(FILE *stream);
// 从文件中获取一个字符串
char *fgets(char *s, int size, FILE *stream);
// 从终端获取一个字符
int getc(FILE *stream);
// 从终端获取一个字符
int getchar(void);
// 回退字符
int ungetc(int c, FILE *stream);

综合案例:BMI计算器

#include <stdio.h>  

int main() {  
    float height, weight;  
    printf("请输入身高(米):");  
    scanf("%f", &height);  
    printf("请输入体重(千克):");  
    scanf("%f", &weight);  

    float bmi = weight / (height * height);  
    printf("\nBMI值:%.1f\n", bmi);  
    printf("====================\n");  
    printf("18.5以下:偏瘦\n");  
    printf("18.5~24:正常\n");  
    printf("24以上:超重\n");  
    return 0;
}  

运行效果

请输入身高(米):1.75  
请输入体重(千克):68  

BMI值:22.2  
====================  
18.5以下:偏瘦  
18.5~24:正常  
24以上:超重  

🚨 常见错误诊断表

错误现象原因分析解决方案
程序输出乱码格式符与参数类型不匹配检查%d/%f等是否正确
scanf读取错误忘记&符号确保变量前加&(数组除外)
输入字符被跳过缓冲区残留换行符%*cgetchar()清理
浮点数精度显示问题未指定小数位数使用%.2f格式控制

📚 复习要点

  1. 标识符命名三原则:非数字开头、无特殊符号、不重复关键字
  2. 注释的双刃剑:良好的注释提升可读性,过度注释增加维护成本
  3. 输入输出黄金法则
    • printf格式符与参数类型严格对应
    • scanf必须使用地址运算符&(数组名除外)
    • 处理输入缓冲区防止意外错误

第二章 数据类型与运算符

2.1 基本数据类型

📌 四大基础类型详解

类型字节数格式符取值范围/精度示例
char1%c-128 ~ 127 或 0 ~ 255 (无符号)'A' '\n' 65
int4%d-2,147,483,648 ~ 2,147,483,647100 -5 0x1A
float4%f±3.4e-38 ~ ±3.4e38(6位有效数字)3.14f -0.5f
double8%lf±1.7e-308 ~ ±1.7e308(15位有效数字)3.1415926

🚨 特殊类型补充

_Bool (C99标准)

_Bool flag = 1;  // 只能存储0或1  

枚举类型

enum Week {Mon, Tue, Wed};  // Mon=0, Tue=1...  

💡 内存布局演示

char c = 'A';        // 内存值:0x41  
int n = 0x12345678;  // 小端存储:78 56 34 12  
float f = 3.14f;     // IEEE754编码:0x4048f5c3  

2.2 类型转换机制

🔄 隐式转换规则

  1. 算术运算转换

    char → short → int → unsigned → long → float → double  
    

    示例

    int a = 5;  
    double b = 3.14;  
    double result = a + b;  // a自动转为double  
    
  2. 赋值转换

    int n = 3.14;    // n=3(截断小数部分)  
    float f = 10;    // f=10.0f  
    

⚠️ 显式强制转换

int a = 5, b = 2;  
double quotient = (double)a / b;  // → 2.5  

风险提示

double d = 3.99;  
int n = (int)d;    // n=3(直接截断,非四舍五入)  

2.3 运算符全解

📊 运算符表

运算符类别运算符
算术运算符+,-,*,/,%
赋值运算符=,+=,-=,*=,/=,%=
关系运算符== , ! = , > , < ,> = ,< =
逻辑运算符&&,|| ,!
位运算符&,|,^,~,<<,>>
条件运算符? :
自增自减运算符++,--
逗号运算符,
指针运算符* &
sizeof运算符sizeof

📊 运算符优先级表

优先级运算符结合性
1() [] .从左到右
2! ~ ++ -- sizeof typeid从右到左
3* / %从左到右
4+ -从左到右
5<< >>从左到右
6< <= > >=从左到右
7== !=从左到右
8&从左到右
9^从左到右
10``
11&&从左到右
12`
13?:从右到左
14= += -= *= /= %= <<= >>= &= ^= `=`
15,从左到右
  • [] () .:这些运算符用于数组下标、函数调用和成员访问。
  • ! ~ ++ --:逻辑非、按位取反、自增自减运算符,通常是前缀形式。
  • \* / %:乘法、除法和求余运算符,优先级相对较高。
  • + -:加法和减法运算符。
  • << >>:位移运算符,处理二进制位的移位操作。
  • & ^ |:按位与、按位异或和按位或运算符。
  • && ||:逻辑与、逻辑或运算符。
  • ?::三元运算符,是条件表达式的一部分。
  • = += -=:赋值运算符,赋值和复合赋值的操作符。

这个优先级表适用于 C 语言,能帮助理解不同运算符的计算顺序。

🛠️ 重点运算符详解

1. 算术运算符

int a = 7, b = 3;  
printf("%d\n", a / b);    // 2(整数除法)  
printf("%f\n", 7.0 / 3);  // 2.333333  
printf("%d\n", a % b);    // 1  

2. 关系运算符

if(5 == 5.0) { ... }  // 成立(值相等)  
if(5 === 5.0) { ... } // ❌ C语言无===运算符  

3. 逻辑运算符

短路特性

int a = 0;  
if(a != 0 && 10/a > 1) {  // 避免除零错误  
    // 不会执行右侧判断  
}  

4. 位运算符

unsigned char flags = 0x0A;  // 0000 1010  
flags |= 0x01;              // 0000 1011 → 设置最低位  
flags &= ~0x08;             // 0000 0011 → 清除第4位  

5. 复合赋值运算符

int x = 5;  
x += 3;    // x=8  
x <<= 1;   // x=16  

🚨 常见错误诊断室

错误代码问题分析解决方案
int a = 3.14;隐式转换丢失精度显式强制转换或修改变量类型
if(a = 5)赋值替代比较改为if(5 == a)
10 % 3.5浮点数取模非法使用fmod()函数
i++ + ++i未定义行为避免同一变量多次修改

📚 综合案例:单位转换器

#include <stdio.h>  

int main() {  
    int choice;  
    double input;  
    printf("1. 英寸→厘米\n2. 磅→千克\n选择:");  
    scanf("%d", &choice);  

    if(choice == 1) {  
        printf("输入英寸:");  
        scanf("%lf", &input);  
        printf("%.2f英寸 = %.2f厘米\n", input, input*2.54);  
    } else if(choice == 2) {  
        printf("输入磅:");  
        scanf("%lf", &input);  
        printf("%.2f磅 = %.2f千克\n", input, input*0.4535924);  
    } else {  
        printf("无效选择!\n");  
    }  
    return 0;  
}  

运行效果

1. 英寸→厘米  
2. 磅→千克  
选择:1  
输入英寸:10  
10.00英寸 = 25.40厘米  

知识巩固练习

  1. 计算表达式 5 + 3 * 2 / (7 - 4) 的值
  2. 写出将变量a的第3位设置为1的位运算表达式
  3. 分析以下代码的输出:
    int a = 3, b = 5;  
    printf("%d", a++ + ++b);  
    

答案

  1. 5 + 3*2/3 = 5+2 = 7
  2. a |= (1 << 2);
  3. 3 + 6 = 9(执行后a=4, b=6)

第三章 流程控制基础

3.1 选择结构

📌 核心语法

1、单分支结构

if(条件) {  
    // 条件为真时执行  
}  

示例

if(score >= 60) {  
    printf("及格!🎉");  
}  

2、双分支结构

if(条件) {  
    // 真分支  
} else {  
    // 假分支  
}  

示例

if(temperature > 30) {  
    printf("开启空调❄️");  
} else {  
    printf("保持通风🌬️");  
}  

3、多分支结构

if(条件1) {  
    // 情况1  
} else if(条件2) {  
    // 情况2  
} else {  
    // 默认情况  
}  

示例

if(score >= 90) {  
    grade = 'A';  
} else if(score >= 70) {  
    grade = 'B';  
} else {  
    grade = 'C';  
}  

🚨 常见错误

错误代码问题分析解决方案
if(a = 5)赋值替代比较改为if(5 == a)
if(1 < a < 5)逻辑表达式错误改为a>1 && a<5
else 匹配错误未正确缩进使用大括号明确作用域

3.2 循环结构

🔄 三大循环对比

循环类型语法执行特点适用场景
whilewhile(条件){...}先判断后执行不确定循环次数
do-whiledo{...}while(条件);先执行一次后判断至少执行一次
forfor(初始化;条件;更新){...}精确控制循环次数已知循环范围

💡 实战案例

1、while循环

int count = 0;  
while(count < 5) {  
    printf("%d ", count);  
    count++;  
}  
// 输出:0 1 2 3 4  

2、for循环

for(int i=0; i<5; i++) {  
    printf("★");  // 打印五角星  
}  

3、do-while循环

char choice;  
do {  
    printf("是否继续?(Y/N): ");  
    scanf(" %c", &choice);  
} while(choice == 'Y');  

第四章 函数初步

4.1 函数定义与调用

📌 函数三要素

1、函数声明

// 声明(告诉编译器函数存在)  
int add(int a, int b);  

2、函数定义

// 定义(实现功能)  
int add(int a, int b) {  
    return a + b;  
}  

3、函数调用

int result = add(3, 5);  // result = 8  

🔄 参数传递机制

  • 值传递:函数内修改形参不影响实参

    void swap(int a, int b) {  
        int temp = a;  
        a = b;  
        b = temp;  // ❌ 无法改变外部变量的值  
    }  
    

4.2 常用库函数

📚 标准库速查

库文件常用函数功能说明
stdio.hprintf(), scanf()输入输出
math.hsqrt(), pow(x,y)数学运算
string.hstrlen(), strcpy()字符串处理
stdlib.hrand(), malloc()随机数/内存管理

💡 案例:生成随机数

#include <stdio.h>  
#include <stdlib.h>  
#include <time.h>  

int main() {  
    srand(time(0));  // 初始化随机种子  
    int num = rand() % 100;  // 生成0-99的随机数  
    printf("随机数:%d", num);  
    return 0;  
}  

第五章 数组基础

5.1 一维数组

📌 定义与初始化

int arr1[5];               // 声明未初始化  
int arr2[3] = {1, 2, 3};   // 完全初始化  
int arr3[] = {1,2,3,4};    // 自动推断长度  

🚨 数组越界风险

int arr[5] = {0};  
arr[5] = 10;  // ❌ 越界访问!可能引发段错误  

🔄 数组遍历

for(int i=0; i<5; i++) {  
    printf("%d ", arr[i]);  
}  

5.2 字符数组

📌 字符串存储

char str1[] = {'H', 'e', 'l', 'l', 'o', '\0'};  
char str2[] = "Hello";  // 自动添加'\0'  

⚠️ 常见错误

错误代码问题分析解决方案
char str[5] = "Hello";长度不足(需6字节)改为str[6]
str1 = str2;数组不能直接赋值使用strcpy()

💡 字符串操作函数

char s1[20] = "Hello";  
char s2[] = "World";  

strcat(s1, s2);  // s1 → "HelloWorld"  
int len = strlen(s1);  // len = 10  

综合案例:成绩统计系统

#include <stdio.h>  
#define MAX 50  

int main() {  
    int scores[MAX], sum = 0;  
    int n;  

    printf("输入学生人数:");  
    scanf("%d", &n);  

    for(int i=0; i<n; i++) {  
        printf("输入第%d个成绩:", i+1);  
        scanf("%d", &scores[i]);  
        sum += scores[i];  
    }  

    printf("平均分:%.2f", (float)sum / n);  
    return 0;  
}  

🚨 高频错误总结

  1. 循环变量越界

    for(int i=0; i<=5; i++)  // 当数组大小为5时越界  
    
  2. 函数未声明

    add(3,5);  // ❌ 若未提前声明add函数  
    
  3. 字符串未终止

    char str[5] = {'H','e','l','l','o'};  // 缺少'\0'