C语言程序设计核心知识点总结
C语言是结构化、过程式的编程语言,以其高效、灵活和底层操作能力强而著称,掌握C语言需要理解其语法、思想以及与计算机底层的联系。
第一部分:基础入门
C语言概述
- 特点:高效、灵活、底层、可移植、结构化。
- 程序结构:
#include <stdio.h>:包含标准输入输出库。int main():程序的入口函数,程序从这里开始执行。- 代码块,用于组织语句。
return 0;:表示程序正常结束。
- 编译与执行:源代码 (
.c) -> 预处理 -> 编译 -> 汇编 -> 链接 -> 可执行文件 (.exe或无后缀)。
数据类型
- 基本数据类型:
int:整型,用于存储整数。char:字符型,用于存储单个字符(本质是1字节整数)。float:单精度浮点型,用于存储实数(约7位有效数字)。double:双精度浮点型,用于存储实数(约15位有效数字)。
- 修饰符:
short,long,long long:改变整型的范围。signed,unsigned:指定整型是否包含负数。
- 类型大小:使用
sizeof()运算符可以获取数据类型或变量所占的字节数。
常量与变量
- 变量:
- 定义:
数据类型 变量名;(e.g.,int age;) - 初始化:
数据类型 变量名 = 初始值;(e.g.,int age = 25;) - 命名规则:字母、数字、下划线组成,不能以数字开头,不能是关键字。
- 定义:
- 常量:
- 字面量常量:
10,'A',14 const修饰符:const int MAX = 100;(定义一个只读变量)#define宏定义:#define PI 3.14(在预处理阶段进行文本替换)
- 字面量常量:
运算符
- 算术运算符:, , , , (取模), (自增), (自减)。
注意: 对整数运算会截断小数部分; 只能用于整数。
- 关系运算符:
>,<,>=,<=, , ,结果为1(真) 或0(假)。 - 逻辑运算符:
&&(与), (或), (非),用于组合多个条件。 - 位运算符:
&(按位与), (按位或),^(按位异或), (按位取反),<<(左移),>>(右移)。 - 赋值运算符:, , , , 等。
- 其他运算符:
sizeof:获取数据类型大小。&:取地址运算符。- 指针解引用运算符。
- 条件运算符(三元运算符)。
输入与输出
printf():格式化输出。- 格式控制符:
%d(int),%c(char),%f(float),%lf(double),%s(字符串),%p(地址)。 - 转义字符:
\n(换行),\t(制表符),\0(字符串结束符)。
- 格式控制符:
scanf():格式化输入。- 关键:必须为变量提供地址,使用
&符号 (e.g.,scanf("%d", &age);)。 - 注意:
scanf读取字符串时,遇到空格会停止,且不会自动吸收换行符。
- 关键:必须为变量提供地址,使用
第二部分:流程控制
选择结构
if-else语句:根据条件执行不同的代码块。if (条件) { // 代码块1 } else if (条件) { // 代码块2 } else { // 代码块3 }switch语句:用于多分支选择,基于一个表达式的值。switch (表达式) { case 常量1: ...; break; case 常量2: ...; break; default: ...; }break关键字用于跳出switch。default处理所有未匹配的情况。
循环结构
while循环:先判断条件,条件为真则执行循环体。while (条件) { // 循环体 }do-while循环:先执行一次循环体,再判断条件。do { // 循环体 } while (条件);for循环:最常用的循环,通常用于明确知道循环次数的场景。for (初始化表达式; 条件表达式; 更新表达式) { // 循环体 }- 循环控制:
break:立即终止整个循环。continue:跳过本次循环的剩余语句,直接进入下一次循环。
第三部分:函数
函数基础
- 定义:
返回类型 函数名(参数列表) { 函数体; }- 返回类型:函数返回值的类型,若无返回值则为
void。 - 参数列表:传递给函数的数据,可以没有参数或多个参数。
- 返回类型:函数返回值的类型,若无返回值则为
- 声明:
返回类型 函数名(参数列表);(函数原型)作用:告诉编译器函数的存在及其类型,通常放在文件开头。
- 调用:
函数名(实参列表);- 值传递:C语言中,函数参数默认是值传递,即传递的是实参的副本,在函数内部修改形参不会影响实参。
- 递归:函数直接或间接地调用自身,必须有明确的递归终止条件。
作用域与生命周期
- 局部变量:在函数内部定义,作用域仅限于该函数,生命周期从函数调用开始到函数结束。
- 全局变量:在所有函数外部定义,作用域为整个程序,生命周期贯穿整个程序运行期间。
- 注意:应尽量避免使用全局变量,因为它会增加程序的耦合度,难以维护。
第四部分:数组与字符串
一维数组
- 定义:
数据类型 数组名[数组大小];(e.g.,int scores[10];) - 初始化:
int arr[5] = {1, 2, 3, 4, 5};int arr[] = {1, 2, 3};// 编译器自动确定大小为3
- 访问:通过下标,从
0开始。arr[0]访问第一个元素。 - 内存布局:数组在内存中是连续存储的。
字符串
- 本质:字符数组,以
\0(空字符) 作为结尾。 - 表示方式:
- 字符数组:
char str[] = "Hello";或char str[] = {'H', 'e', 'l', 'l', 'o', '\0'}; - 字符串指针:
char *str = "Hello";// 指向字符串字面量的常量指针
- 字符数组:
- 常用函数 (需包含
<string.h>):strlen(str):求字符串长度 (不包括\0)。strcpy(dest, src):字符串拷贝 (将src拷贝到dest)。strcat(dest, src):字符串拼接 (将src拼接到dest后面)。strcmp(str1, str2):字符串比较 (返回 0, 负数, 正数)。
多维数组
- 二维数组:
数据类型 数组名[行数][列数];(e.g.,int matrix[3][4];) - 初始化:
int matrix[2][3] = { {1, 2, 3}, {4, 5, 6} }; - 内存布局:二维数组在内存中也是线性连续存储的,按行优先存放。
第五部分:指针 (C语言的灵魂)
指针基础
- 定义:指针是一个变量,其存储的是另一个变量的内存地址。
- 语法:
数据类型 *指针变量名;(e.g.,int *p;)
- 语法:
- 核心运算符:
&(取地址):获取变量的内存地址。p = &a;- (解引用/间接寻址):通过指针访问其指向的内存中的值。
printf("%d", *p);
- 指针与数组:
- 数组名
arr通常会“衰变”为其首元素的地址。p = arr;等价于p = &arr[0]; - 可以通过指针遍历数组:
*(p + i)等价于arr[i]。
- 数组名
- 指针与函数:
- 指针作为参数:可以实现“地址传递”,从而在函数内部修改外部变量的值,这是C语言实现“引用传递”效果的主要方式。
- 指针作为返回值:函数可以返回一个指针,指向某个变量或内存区域。
指针进阶
- 指针的指针:指向指针的指针。
- 函数指针:指向函数的指针,可以用于将函数作为参数传递给其他函数,实现回调机制。
- 语法:
返回类型 (*指针名)(参数列表);(e.g.,int (*p_func)(int, int);)
- 语法:
const与指针:const int *p:p可变,但p指向的内容(*p)不可变。int *const p:p不可变,但p指向的内容可变。const int *const p:p和*p都不可变。
第六部分:内存管理
动态内存分配
- 目的:在程序运行时根据需要动态地分配和释放内存,避免了静态数组的固定大小限制。
- 相关函数 (需包含
<stdlib.h>):malloc(size_t size):分配size字节的内存块,返回一个指向该内存块起始地址的指针,内存是未初始化的。calloc(size_t num, size_t size):分配num * size字节的内存块,并将所有位初始化为0。free(void *ptr):释放之前通过malloc或calloc分配的内存块。防止内存泄漏!realloc(void *ptr, size_t new_size):调整之前分配的内存块的大小。
第七部分:结构体、联合体与枚举
结构体
- 定义:将不同类型的数据组合成一个单一的复合类型。
struct Student { char name[50]; int age; float score; }; - 声明与使用:
struct Student s1; // 声明一个结构体变量 strcpy(s1.name, "Zhang San"); s1.age = 20;
- 结构体指针:通过
->运算符访问成员。s1.age等价于ptr->age。
联合体
- 定义:一种特殊的数据类型,允许在相同的内存位置存储不同的数据类型。
- 特点:所有成员共享同一块内存,大小是最大成员的大小,修改一个成员会影响其他成员。
- 用途:当需要在不同时间以不同类型使用同一块内存时使用。
枚举
- 定义:定义一个命名常量的集合。
enum Weekday {MON, TUE, WED, THU, FRI, SAT, SUN}; - 特点:默认情况下,枚举常量的值从
0开始递增,可以手动指定值。enum Weekday today = MON;
第八部分:文件操作
文件I/O
- 文件指针:使用
FILE *类型的指针来标识和操作文件。 - 相关函数 (需包含
<stdio.h>):fopen(const char *filename, const char *mode):打开文件,返回文件指针。- 模式:
"r"(读),"w"(写, 覆盖),"a"(追加),"rb","wb"(二进制模式) 等。
- 模式:
fclose(FILE *stream):关闭文件。fgetc(FILE *stream):从文件中读取一个字符。fputc(int c, FILE *stream):向文件中写入一个字符。fgets(char *str, int n, FILE *stream):从文件中读取一行。fputs(const char *str, FILE *stream):向文件中写入一行。fscanf(FILE *stream, const char *format, ...):格式化读取。fprintf(FILE *stream, const char *format, ...):格式化写入。fread(void *ptr, size_t size, size_t count, FILE *stream):二进制读取。fwrite(const void *ptr, size_t size, size_t count, FILE *stream):二进制写入。fseek(FILE *stream, long offset, int origin):移动文件指针。
第九部分:预处理器与高级主题
预处理器
#include:包含头文件。#define:宏定义,进行简单的文本替换。- 带参宏:
#define MAX(a, b) ((a) > (b) ? (a) : (b))(注意括号)
- 带参宏:
- 条件编译:
#ifdef,#ifndef,#endif,#else,#elif- 用于根据条件选择性地编译代码,常用于跨平台开发和头文件保护。
其他重要概念
- 命令行参数:
main函数可以接收参数。int main(int argc, char *argv[])argc:参数计数 (包括程序名)。argv:参数向量 (字符串数组)。
- 位域:在结构体中,以位为单位来指定成员的内存长度,用于节省空间。
- 错误处理:C语言没有内置的异常处理机制,通常通过函数返回值、全局变量
errno或更复杂的错误码系统来处理错误。
学习建议
- 动手实践:编程是门手艺,光看不练是学不会的,多写代码,多调试。
- 理解内存:C语言的核心是操作内存,画出变量、数组、指针在内存中的布局,有助于深刻理解指针和数组。
- 善用调试器:学习使用 GDB (Linux) 或 Visual Studio Debugger (Windows) 来单步执行代码,观察变量变化,是排查问题的利器。
- 阅读优秀代码:阅读一些开源的、高质量的C语言项目(如SQLite的一部分),学习其编码风格和设计思想。
- 从底层向上:理解计算机是如何工作的(CPU、内存、寄存器),会让你对C语言有更本质的认识。
这份总结涵盖了C语言的绝大部分核心知识点,希望能对你的学习和复习有所帮助!
