C语言核心概念复习——C语言基础阶段

C语言基础阶段

一、C语言关键字

1. static(静态修饰符)

两种用法

复制代码
// 1. 限制全局变量和函数的作用域(只能在当前文件使用)
static int global_var = 10;  // 只能在当前文件访问
static void func(void) {      // 只能在当前文件调用
    // ...
}

// 2. 延长局部变量的生命周期(只会初始化一次)
void test(void) {
    static int count = 0;     // 只在第一次调用时初始化为0
    count++;                  // 每次调用count都会保持上次的值
    printf("%d\n", count);
}

// 调用test()三次的输出:
// 第一次: 1
// 第二次: 2  
// 第三次: 3

2. extern(外部声明)

作用:声明一个外部符号(函数/全局变量)可以在本文件中使用

复制代码
// file1.c
int global_value = 100;      // 定义全局变量

// file2.c
extern int global_value;     // 声明外部变量,告诉编译器在别的文件中
extern void external_func(void);  // 声明外部函数

void test(void) {
    printf("%d\n", global_value);  // 可以使用file1.c中的变量
}

3. const(常量修饰符)

作用:修饰符号为只读(99%情况下指的是变量)

复制代码
const int MAX_SIZE = 100;    // MAX_SIZE是只读的
// MAX_SIZE = 200;          // 错误!不能修改const变量

// 指针相关的const
const char *p1;              // p1指向的内容是常量(不能通过p1修改)
char * const p2;             // p2本身是常量(不能修改p2指向的地址)
const char * const p3;       // p3和它指向的内容都是常量

4. volatile(易失性修饰符)

作用:每次都从内存地址中访问数据,防止编译器优化

复制代码
volatile int flag = 0;  // 告诉编译器不要优化这个变量

// 常用于:
// 1. 多线程共享的变量
// 2. 硬件寄存器
// 3. 中断服务程序修改的变量

二、数组、指针、函数

1. 指针相关概念

复制代码
// 基本指针
int a = 10;
int *p = &a;                // p是指向int的指针

// 函数指针:指向函数的指针
int (*pfun)(int);          // pfun指向返回int,参数为int的函数
// 对应的函数:int func(int a);

// 指针函数:返回值类型为指针的函数
int *func(int a);          // func函数返回int指针

// 数组指针:指向数组的指针
int (*parr)[10];           // parr指向包含10个int的数组
// 对应的数组:int arr[10];

// 指针数组:元素类型为指针的数组
int *arr[10];              // arr是包含10个int指针的数组

// 函数指针数组:元素类型为函数指针的数组
int (*func_arr[10])(int);  // 包含10个函数指针的数组

三、结构体和内存对齐

1. 结构体定义

复制代码
// 定义一个新类型
struct Student {
    char name[20];
    int age;
    float score;
};

// 使用
struct Student stu1;
stu1.age = 20;

// 或者使用typedef
typedef struct {
    char name[20];
    int age;
} Person;
Person p1;  // 可以直接使用

2. 内存对齐

复制代码
// 设置内存对齐方式
#pragma pack(1)     // 按1字节对齐
struct Test1 {
    char a;
    int b;
};                  // 大小为5字节

#pragma pack(4)     // 按4字节对齐(默认)
struct Test2 {
    char a;
    int b;
};                  // 大小为8字节(有3字节填充)

// Linux中的对齐方式
struct Test3 {
    char a;
    int b;
} __attribute__((packed));  // 按1字节对齐

3. 共用体(联合体)

复制代码
union Data {
    int i;
    float f;
    char str[20];
};

// 所有成员共用同一段内存
// 大小为最大成员的大小(20字节)

四、预处理和宏定义

1. 宏定义

复制代码
// 简单宏
#define PI 3.14159

// 带参宏
#define MAX(a, b) ((a) > (b) ? (a) : (b))
#define SQUARE(x) ((x) * (x))

// 使用
int max_val = MAX(10, 20);
int square_val = SQUARE(5);  // ((5) * (5))

2. 条件编译

复制代码
// 基本条件编译
#if 1
    // 这部分代码会被编译
#else
    // 这部分不会
#endif

// 防止头文件重复包含
#ifndef MY_HEADER_H
#define MY_HEADER_H
// 头文件内容
#endif

// 根据平台编译
#ifdef LINUX
    // Linux专用代码
#elif defined(WINDOWS)
    // Windows专用代码
#endif

五、C语言编译过程

4个阶段:

复制代码
main.c  →  main.i  →  main.s  →  main.o  →  mainapp(bin)
   ↓         ↓          ↓          ↓           ↓
源代码    预处理后    汇编代码    目标文件    可执行程序

1. 预处理(Preprocessing)

处理内容

  • 去掉注释

  • 宏替换

  • 头文件展开

  • 特殊符号处理

复制代码
// main.c 中的代码
printf("%s %d i = %d\n", __FILE__, __LINE__, i);
// 预处理后变成(假设在test.c第5行)
printf("test.c 5 i = %d\n", i);

生成文件.i文件(符合C语法的纯文本文件)

2. 编译(Compilation)

作用:C语言源文件转换为汇编文件

  • 进行C语言的语法分析

  • 检查语法错误

  • 生成中间代码

生成文件.s文件(汇编文件)

3. 汇编(Assembly)

作用:汇编程序转换为二进制机器码

  • 将汇编指令转换为机器指令

  • 生成可重定位的目标文件

生成文件.o文件(目标文件,二进制机器码)

4. 链接(Linking)

作用 :将所有.o文件链接为可执行程序

  • 解决符号引用(函数调用、变量引用)

  • 合并各个模块

  • 添加启动代码

生成文件:可执行二进制文件

注意 :1-3阶段每个.c文件独立处理,n个.c文件会生成n个.o文件

六、文件编程

1. 两种IO接口

复制代码
// 标准IO(有缓冲区,效率高)
#include <stdio.h>
FILE *fp = fopen("file.txt", "r");
fread(buffer, 1, size, fp);
fclose(fp);

// 系统IO(无缓冲区,效率低,仅Linux)
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
int fd = open("file.txt", O_RDONLY);
read(fd, buffer, size);
close(fd);

2. 缓冲类型

  • 无缓冲:立即读写(如系统IO)

  • 行缓冲:遇到换行符或缓冲区满时刷新(如终端输出)

  • 全缓冲:缓冲区满时刷新(如文件操作)

3. 性能测试

复制代码
// 测试磁盘IO效率
// 方法1:每次写1字节,写1000次(效率最低)
// 方法2:每次写100字节,写1000次(效率中等)
// 方法3:每次写1000字节,写1次(效率最高)

// 文件空洞:文件中间有未写入数据的部分
lseek(fd, 1024, SEEK_SET);  // 跳到1024字节位置
write(fd, "data", 4);        // 创建文件空洞

七、进程与线程

1. 进程空间布局(4GB)

复制代码
0xFFFFFFFF (4GB) ┌─────────────────┐
                 │     Kernel      │
                 │    (内核空间)   │
0xC0000000 (3GB) ├─────────────────┤ ← 内核空间与用户空间分界线
                 │                 │
                 │     Stack       │ ← 线程独享(每个线程有自己的栈)
                 │      (栈)       │
                 ├─────────────────┤
                 │   Memory Map    │ ← 库函数地址映射区
                 │      (映射)     │
                 ├─────────────────┤
                 │      Heap       │ ← 动态分配内存(需要手动管理)
                 │      (堆)       │
                 ├─────────────────┤
                 │       BSS       │ ← 未初始化的全局/静态变量
                 │                 │
                 ├─────────────────┤
                 │      Data       │ ← 初始化的全局/静态变量
                 │      (数据段)   │
                 ├─────────────────┤
                 │      Code       │ ← 程序代码(二进制指令)
                 │      (代码段)   │
0x00000000 (0GB) └─────────────────┘

2. 各段说明

  • Code段:存储程序二进制代码(只读)

  • Data段:存储初始化为非0的全局变量和静态变量

  • BSS段:存储未初始化或初始化为0的全局变量和静态变量

  • Heap段:用户自行管理的动态内存(malloc/free)

  • Stack段:线程独享,存储局部变量、函数参数、返回地址

  • Map段:存储共享库函数的地址映射

  • Kernel段:内核空间,用户程序不能直接访问

3. 进程 vs 线程

特性 进程 线程
空间大小 4GB(用户空间3GB) 共享进程空间
每个进程有自己的栈 每个线程有独立栈(8MB)
创建效率 低(需要复制资源) 高(共享资源)
通信复杂度 复杂(需要IPC机制) 简单(共享内存)
稳定性 高(相互隔离) 低(相互影响)
资源开销

九、网络基础

1. 网络模型对比

复制代码
OSI七层模型           TCP/IP四层模型
7. 应用层             应用层
6. 表示层
5. 会话层
4. 传输层             传输层
3. 网络层             网络层
2. 数据链路层         网络接口层
1. 物理层

2. TCP vs UDP

特性 TCP UDP
连接 有连接 无连接
通信模式 一对一 一对多/多对多
数据传输 数据流 数据报(包)
可靠性 高(有应答机制)
效率
特性 拥塞控制、重传机制 无控制机制

3. 数据包封装过程

复制代码
应用层数据
    ↓
+----------------+
|  TCP/UDP头部   |  ← 传输层
+----------------+
|     IP头部     |  ← 网络层
+----------------+
|   以太网头部    |  ← 链路层
|   以太网校验    |
+----------------+
实际在以太网中传输的数据帧

4. 各层头部关键字段

IP头部(网络层)

  • 32位源IP地址

  • 32位目的IP地址

  • 8位协议类型(TCP=6, UDP=17)

  • 16位总长度

TCP头部(传输层)

  • 16位源端口

  • 16位目的端口

  • 32位序列号(数据包序号)

  • 32位确认号(应答序号)

  • 6位标志位(SYN、ACK、FIN等)

  • 16位窗口大小(接收端缓冲区大小)

以太网头部(链路层)

  • 6字节目的MAC地址

  • 6字节源MAC地址

  • 2字节类型(0800=IP, 0806=ARP)

  • 46-1500字节数据

  • 4字节CRC校验

相关推荐
logocode_li3 小时前
说透 Linux Shell:命令与语法的底层执行逻辑
linux·运维·ssh
CHENKONG_CK3 小时前
晨控CK-LR08-E00与汇川H5U系列PLC配置MODBUSTCP通讯连接手册
linux·服务器·网络
㓗冽3 小时前
60题之内难题分析
开发语言·c++·算法
LongQ30ZZ3 小时前
Linux-基础IO
linux
dingdingfish3 小时前
Bash学习 - 第3章:Basic Shell Features,第5节:Shell Expansions
开发语言·学习·bash
rainbow68893 小时前
C++开源库dxflib解析DXF文件实战
开发语言·c++·开源
deepxuan3 小时前
Day7--python
开发语言·python
John_ToDebug3 小时前
Chromium安全架构深度解析:从悬空指针检测到内存安全防御体系
c++·chrome
来鸟 鸣间3 小时前
Linux下3个so库之间的关系
linux·运维