由浅入深C语言知识汇总(上篇,超详细!)

        C 语言是一种广泛使用的计算机编程语言,由美国贝尔实验室的丹尼斯・里奇(Dennis Ritchie)在 20 世纪 70 年代初设计开发。它兼具高级语言的易用性和低级语言的直接硬件访问能力,是许多系统软件、应用程序和编程语言的基础,至今仍在编程领域占据重要地位。

一,C语言概述

1、C 语言的发展背景

        起源:1972 年,丹尼斯・里奇在开发 UNIX 操作系统时,为了解决 B 语言的局限性(如缺乏类型检查、难以处理复杂数据结构)而设计了 C 语言。UNIX 系统的大部分代码后来都用 C 语言重写,二者相互促进,推动了彼此的普及。

        标准化:1989 年,美国国家标准协会(ANSI)发布了 C 语言的第一个标准(ANSI C,即 C89);1990 年,国际标准化组织(ISO)采纳该标准,命名为 C90。此后又经历了多次修订,形成了 C99、C11、C17 等版本,逐步增加了新特性(如布尔类型、变长数组、泛型宏等)。

2、C 语言的核心特点

结构化编程
支持顺序、选择(if-else)、循环(for、while)等控制结构,鼓励模块化设计(通过函数拆分程序),使代码更清晰、易维护。

高效性

语法简洁,编译后生成的机器码执行效率接近汇编语言,适合对性能要求高的场景(如操作系统、嵌入式系统)。允许直接操作内存(通过指针),但也增加了内存泄漏、越界访问等风险。

可移植性
标准 C 语言代码在不同操作系统(如 Windows、Linux、macOS)和硬件平台上只需少量修改即可编译运行,这也是其广泛应用的重要原因

功能丰富且灵活

支持基本数据类型(int、float、char 等)和复杂数据结构(数组、结构体、枚举、联合体)。

提供预处理指令(如#include#define),方便代码复用和条件编译。允许直接调用汇编代码,进一步扩展了底层操作能力。

3、C 语言的应用领域

系统软件:操作系统(如 UNIX、Linux 内核)、编译器、数据库管理系统(如 MySQL 部分模块)等。

嵌入式系统:智能设备(如路由器、智能家居)、汽车电子、工业控制等,因 C 语言对硬件资源占用少、效率高。

应用软件:早期的许多桌面应用(如部分图形界面程序)、游戏引擎核心模块等。

编程语言基础:C++、Java、Python 等许多语言的设计都借鉴了 C 语言的语法,掌握 C 语言有助于理解其他语言的底层逻辑。

4、学习 C 语言的意义

理解计算机底层工作原理(如内存管理、指针操作),建立编程的 “底层思维”。

为学习更复杂的语言(如 C++、Go)或领域(如操作系统开发、逆向工程)打下基础。

培养严谨的编程习惯,因为 C 语言对语法和内存管理的要求较严格,能帮助开发者规避常见错误。

二,基本语法结构

1、预处理指令:#include 与 #define

预处理指令是在程序编译前由预处理器执行的命令,以#开头,且不需要分号结尾。它们用于处理代码结构、定义常量或引入外部资源。

#include:引入头文件
功能:将指定头文件的内容插入到当前代码中,用于获取库函数声明、宏定义或类型定义。
两种格式:

#include <头文件名>用于引入系统标准库头文件(如stdio.hstdlib.h,编译器会到系统默认路径查找。

#include "头文件名"用于引入用户自定义头文件(如myfunc.h,编译器优先在当前项目路径查找,找不到再去系统路径。

#include <stdio.h>   // 引入标准输入输出库,使用printf、scanf等函数
#include "calc.h"   // 引入自定义的计算相关头文件

#define:定义宏(符号常量或代码片段)
功能:用一个标识符替代一段文本,分为无参数宏带参数宏

无参数宏(符号常量)
格式#define 标识符 替换文本
作用:定义常量,提高代码可读性和可维护性(修改时只需改一处)。

#define PI 3.1415926   // 用PI代替3.1415926
#define MAX_SIZE 100   // 用MAX_SIZE代替100

// 使用示例
float area = PI * r * r;  // 等价于3.1415926 * r * r
int arr[MAX_SIZE];        // 等价于int arr[100];

带参数宏(类似函数的代码片段)
格式:#define 宏名(参数) 替换文本
作用:实现简单逻辑的代码复用,比函数调用更高效(无函数调用开销),但需注意优先级问题。

#define ADD(a, b) (a + b)  // 定义加法宏
#define SQUARE(x) ((x) * (x))  // 加括号避免优先级错误

// 使用示例
int sum = ADD(3, 5);    // 等价于int sum = (3 + 5);
int square = SQUARE(4); // 等价于int square = ((4) * (4));

注意:宏替换是简单的文本替换,不进行语法检查,定义时需谨慎处理运算符优先级(多用括号)。

2、主函数 main():程序的入口

C 程序必须包含且只能包含一个main()函数,它是程序执行的起点(操作系统通过调用main()启动程序)。

基本格式:

int main() {
    // 函数体:程序逻辑
    return 0;  // 返回0表示程序正常结束
}

参数与返回值

        返回值类型为int:用于向操作系统返回程序的执行状态(0表示成功,非0表示异常,具体含义由系统定义)。

        带参数的main()(用于接收命令行参数):

基本格式:

int main(int argc, char *argv[]) {
    // argc:命令行参数的数量(至少为1,包含程序名)
    // argv:参数数组,argv[0]是程序名,argv[1]~argv[argc-1]是实际参数
    return 0;
}

执行流程

程序从main()的第一行代码开始执行,依次执行函数体内的语句,直到遇到return语句或函数结束,程序终止。

3、语句:以分号 ; 结尾

语句是 C 程序中执行具体操作的指令,必须以分号;作为结束标志,分号是语句的 “终止符”。

简单语句

  • 赋值语句:int a = 5;
  • 函数调用语句:printf("Hello");
  • 空语句:;(什么也不做,有时用于循环体占位)。

复合语句
由多个简单语句组成,通常被代码块({})包裹,但仍需注意内部语句的分号。

int x = 10;
if (x > 5) {
    printf("x大于5\n");  // 内部语句需分号
    x = 0;              // 内部语句需分号
}  // 代码块

注意:遗漏分号是常见错误,会导致编译器报错(提示 “语法错误”)。

          代码块可以嵌套(花括号内再包含花括号)。

          良好的缩进习惯(如每个代码块内的语句缩进 4 个空格)能提高代码可读性。

三,核心概念

1. 数据类型

基本类型

基本类型是 C 语言中最基础的数据存储形式,直接对应硬件层面的存储单元。

整型:用于存储整数,根据取值范围和占用内存分为以下几种:

  • int:最常用的整数类型,通常占用 4 字节(32 位),取值范围约为 - 21 亿~21 亿。
  • short(或short int):短整型,占用 2 字节(16 位),取值范围约为 - 32768~32767,适合存储较小的整数以节省内存。
  • long(或long int):长整型,通常占用 4 字节(32 位)或 8 字节(64 位),取值范围更大。
  • char:字符型,本质是 1 字节(8 位)的整数,用于存储 ASCII 字符(如'A'的 ASCII 值为 65),也可作为最小的整数类型使用。
    示例:
int num = 100;
short year = 2023;
long population = 1400000000;
char grade = 'B';  // 等价于 char grade = 66;

浮点型:用于存储带小数的数值,支持科学计数法表示。

  • float:单精度浮点型,占用 4 字节,精度约为 6~7 位有效数字,赋值时需加f后缀(如3.14f)。
  • double:双精度浮点型,占用 8 字节,精度约为 15~17 位有效数字,是默认的浮点类型(如3.14默认为double)。
    示例:
    float pi_float = 3.14159f;
    double pi_double = 3.1415926535;
    double distance = 1.5e3;  // 科学计数法,等价于1500.0
    派生类型

    派生类型基于基本类型扩展,用于表示更复杂的数据结构。

  • 数组:相同类型元素的有序集合,通过下标访问元素(下标从 0 开始)。
  • 定义格式:类型 数组名[长度];
int scores[5] = {90, 85, 95, 88, 92};  // 定义包含5个整数的数组
char name[6] = "Alice";  // 字符数组(字符串),末尾自动添加'\0'结束符
  • 指针:存储变量内存地址的变量,通过*操作符访问指向的变量值,通过&操作符获取变量地址。
int a = 10;
int *p = &a;  // p指向a的地址
printf("%d", *p);  // 输出10(访问p指向的变量值)
  • 结构体:自定义的复合类型,可包含不同类型的成员,用于描述一个 "实体" 的多个属性。
struct Student {
    char name[20];
    int age;
    float score;
};
struct Student s = {"Tom", 18, 90.5};  // 定义结构体变量并初始化
  • 共用体(联合体):与结构体类似,但所有成员共享同一块内存(大小为最大成员的大小),同一时间只能存储一个成员的值。
union Data {
    int i;
    float f;
    char c;
};
union Data d;
d.i = 10;  // 存储整数
d.f = 3.14f;  // 覆盖整数,存储浮点数

2. 变量与常量

变量

变量是程序运行中值可以改变的存储单元,使用前必须先声明类型。

  • 声明格式:类型 变量名 = 初始值;(初始化可选,未初始化的变量值不确定)。

  • 作用域:变量的有效范围,如函数内定义的局部变量仅在函数内有效,函数外定义的全局变量在整个文件中有效。

    示例:

int global_var = 100;  // 全局变量

void func() {
    int local_var = 20;  // 局部变量
    global_var += local_var;  // 全局变量可被函数访问
}
常量

常量是值不可改变的量,有两种定义方式:

  • const修饰的常量:具有类型检查,更安全,本质是 "只读变量"。

const int MAX_SIZE = 100;  // 定义整型常量,不可修改
const float PI = 3.14159f;
  • #define定义的宏常量:预编译阶段的文本替换,无类型检查,可定义更复杂的常量或表达式。
#define MAX_AGE 120  // 无类型,直接替换文本
#define AREA(r) (3.14 * (r) * (r))  // 带参数的宏常量(计算圆面积)

区别:const常量在编译阶段生效,有类型;#define在预编译阶段生效,仅做文本替换。

3. 运算符

算术运算符

用于数值计算,注意整数除法会自动截断小数部分。

int a = 10, b = 3;
int sum = a + b;    // 13
int div = a / b;    // 3(整数除法)
int rem = a % b;    // 1(取余,仅用于整数)
关系运算符

用于比较两个值的关系,返回1(真)或0(假)。

int x = 5, y = 10;
int is_eq = (x == y);  // 0(5不等于10)
int is_ge = (x >= 3);  // 1(5大于等于3)
逻辑运算符

用于逻辑判断,遵循 "短路求值" 规则(前半部分可确定结果时,后半部分不执行)。

int a = 1, b = 0;
int and_res = (a && b);  // 0(逻辑与:两者都为真才为真)
int or_res = (a || b);   // 1(逻辑或:至少一个为真则为真)
int not_res = !a;        // 0(逻辑非:取反)
位运算符

直接对二进制位进行操作,常用于底层编程或优化运算。

int a = 6;  // 二进制:0110
int b = 3;  // 二进制:0011
int and_bit = a & b;  // 0010(2,按位与)
int or_bit = a | b;   // 0111(7,按位或)
int xor_bit = a ^ b;  // 0101(5,按位异或)
int shift_left = a << 1;  // 1100(12,左移1位等价于乘2)
赋值运算符

将右侧值赋给左侧变量,复合赋值运算符是简化写法。

int x = 5;
x += 3;  // 等价于x = x + 3 → x=8
x *= 2;  // 等价于x = x * 2 → x=16
x %= 3;  // 等价于x = x % 3 → x=1

4. 控制结构

条件语句

根据条件执行不同分支,else if可用于多条件判断。

int score = 85;
if (score >= 90) {
    printf("优秀");
} else if (score >= 60) {
    printf("及格");  // 执行此分支
} else {
    printf("不及格");
}
循环语句

重复执行代码块,三种循环各有适用场景:

  • while循环:先判断条件,条件为真则执行循环体,适合未知循环次数的场景。

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

do-while循环:先执行一次循环体,再判断条件,至少执行一次。

int j = 1;
do {
    printf("%d ", j);  // 输出:1 2 3
    j++;
} while (j <= 3);

for循环:初始化、条件判断、增量更新集中在一处,适合已知循环次数的场景。

for (int k = 0; k < 3; k++) {
    printf("循环第%d次\n", k+1);  // 输出3次循环信息
}
跳转语句

改变程序执行流程:

  • break:跳出当前循环或switch语句

for (int i = 0; i < 10; i++) {
    if (i == 5) break;  // 当i=5时跳出循环
    printf("%d ", i);  // 输出:0 1 2 3 4
}

continue:跳过本次循环剩余部分,直接进入下一次循环。

for (int i = 0; i < 5; i++) {
    if (i == 2) continue;  // 跳过i=2的循环体
    printf("%d ", i);  // 输出:0 1 3 4
}

goto:无条件跳转到同一函数内的标签处(不推荐使用,易导致代码混乱)。

int x = 1;
if (x == 1) {
    goto label;  // 跳转到label处
}
printf("这里不会执行");
label:
    printf("跳转到这里");

return:结束当前函数并返回值(无返回值的函数用return;)。

总结:

不积硅步无以至千里,不积小流无以成江海。其实C语言的主要知识点就是这些东西,其余的都是在这些基础上的拓展,如果对嵌入式感兴趣可以关注我,以后会循序渐进的分享与嵌入式或我当前了解学习的更多知识点,共勉。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值