news 2026/9/15 9:13:15

C语言从入门到精通:系统化学习指南与实战技巧

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
C语言从入门到精通:系统化学习指南与实战技巧

1. C语言学习笔记:从入门到精通的系统化指南

作为一名在嵌入式领域工作多年的工程师,我经常被问到如何系统学习C语言。今天整理一份完整的C语言学习路线,包含从基础语法到实际项目开发的全部关键知识点。这份笔记特别适合零基础入门和需要巩固基础的开发者。

C语言作为接近硬件的编程语言,在操作系统、嵌入式系统、驱动开发等领域占据不可替代的地位。学习C语言不仅能掌握编程思维,更能深入理解计算机底层工作原理。下面我将按照实际开发中的知识模块划分,带你构建完整的C语言知识体系。

2. C语言核心语法精要

2.1 基础数据类型与运算符

C语言的基础数据类型包括整型(int)、字符型(char)、浮点型(float/double)等。特别要注意不同平台下数据类型的长度差异:

// 32位系统典型长度 int - 4字节 char - 1字节 float - 4字节 double - 8字节

位运算符是C语言的特色之一,常用于硬件寄存器操作:

unsigned char reg = 0x00; reg |= (1 << 3); // 设置第3位为1 reg &= ~(1 << 2); // 清除第2位

注意:位操作前务必确认变量是否为无符号类型,避免符号位带来的意外行为

2.2 控制结构与函数

选择结构中switch-case的break陷阱是常见错误源:

switch(var) { case 1: printf("case 1"); // 缺少break会继续执行case 2 case 2: printf("case 2"); break; }

函数参数传递有值传递和指针传递两种方式。数组作为参数时实际传递的是指针:

void modifyArray(int arr[], int len) { // 这里arr实际是指针 arr[0] = 100; // 会修改原数组 }

3. C语言进阶特性解析

3.1 指针的深入理解

指针是C语言的灵魂所在。理解指针需要掌握几个核心概念:

  1. 指针的指针:用于动态二维数组等场景
  2. 函数指针:实现回调机制的基础
  3. 指针运算:数组遍历的高效方式
int arr[5] = {1,2,3,4,5}; int *p = arr; printf("%d", *(p+2)); // 输出3,等价于arr[2]

常见误区:指针未初始化就解引用会导致段错误。良好的习惯是定义指针时立即初始化为NULL。

3.2 内存管理实战

手动内存管理是C语言的重要特性,也是主要错误来源:

// 动态分配内存 int *ptr = (int*)malloc(10 * sizeof(int)); if(ptr == NULL) { // 必须检查分配是否成功 perror("malloc failed"); exit(EXIT_FAILURE); } // 使用后释放 free(ptr); ptr = NULL; // 避免悬垂指针

内存泄漏检测工具推荐:

  • Valgrind(Linux)
  • Dr. Memory(Windows)

4. 文件操作与系统编程

4.1 文件读写操作

文件操作的基本模式:

FILE *fp = fopen("test.txt", "r+"); if(fp == NULL) { perror("文件打开失败"); return; } char buffer[100]; fgets(buffer, sizeof(buffer), fp); // 读取一行 fprintf(fp, "写入内容"); fclose(fp); // 必须关闭文件

重要提示:文件操作后必须检查返回值并处理错误情况,这是很多初学者忽略的安全隐患。

4.2 系统调用与进程控制

system函数调用会创建新进程,默认是阻塞的:

int status = system("ls -l"); // 阻塞直到命令完成

如果需要非阻塞执行,可以考虑fork+exec组合:

pid_t pid = fork(); if(pid == 0) { // 子进程 execlp("ls", "ls", "-l", NULL); exit(EXIT_FAILURE); // exec失败才会执行到这里 } else if(pid > 0) { // 父进程继续执行 } else { // fork失败 }

5. 数据结构与算法实现

5.1 常用排序算法

快速排序的C语言实现:

void quickSort(int arr[], int left, int right) { if(left >= right) return; int pivot = arr[left]; int i = left, j = right; while(i < j) { while(i < j && arr[j] >= pivot) j--; arr[i] = arr[j]; while(i < j && arr[i] <= pivot) i++; arr[j] = arr[i]; } arr[i] = pivot; quickSort(arr, left, i-1); quickSort(arr, i+1, right); }

5.2 链表操作

单链表的基本结构:

typedef struct Node { int data; struct Node *next; } Node; // 创建新节点 Node* createNode(int data) { Node *newNode = (Node*)malloc(sizeof(Node)); newNode->data = data; newNode->next = NULL; return newNode; } // 链表插入 void insertNode(Node **head, int data) { Node *newNode = createNode(data); newNode->next = *head; *head = newNode; }

6. 工程实践与调试技巧

6.1 Makefile编写规范

基础Makefile示例:

CC = gcc CFLAGS = -Wall -g TARGET = myprogram SRCS = main.c utils.c OBJS = $(SRCS:.c=.o) all: $(TARGET) $(TARGET): $(OBJS) $(CC) $(CFLAGS) -o $@ $^ %.o: %.c $(CC) $(CFLAGS) -c $< clean: rm -f $(OBJS) $(TARGET)

6.2 GDB调试技巧

常用GDB命令:

  • break:设置断点
  • run:启动程序
  • next:单步执行
  • print:查看变量值
  • backtrace:查看调用栈
gcc -g program.c -o program gdb ./program (gdb) break main (gdb) run

7. 常见问题解决方案

7.1 段错误(Segmentation fault)排查

段错误的常见原因:

  1. 访问空指针
  2. 数组越界
  3. 栈溢出
  4. 修改只读内存

排查步骤:

  1. 使用gdb运行程序,定位崩溃位置
  2. 检查指针是否有效
  3. 检查数组访问是否越界
  4. 检查内存分配是否成功

7.2 内存泄漏检测

Valgrind基本用法:

valgrind --leak-check=full ./program

典型输出解读:

  • definitely lost:确认的内存泄漏
  • indirectly lost:间接内存泄漏
  • possibly lost:可能的内存泄漏

8. 项目实战:停车场管理系统

一个完整的C语言项目通常包含以下模块:

// 车辆信息结构体 typedef struct { char plate[10]; // 车牌号 time_t enterTime; // 进入时间 int parkingSpot; // 停车位 } Vehicle; // 系统功能函数 void addVehicle(Vehicle *parkingLot, int size); void removeVehicle(Vehicle *parkingLot, int size); void displayParkingLot(Vehicle *parkingLot, int size);

项目开发要点:

  1. 使用文件持久化数据
  2. 实现菜单驱动界面
  3. 添加输入验证
  4. 考虑并发访问控制

9. 开发环境配置

9.1 VSCode配置C语言环境

  1. 安装C/C++扩展
  2. 配置tasks.json用于构建
  3. 配置launch.json用于调试
  4. 设置c_cpp_properties.json定义包含路径
// tasks.json示例 { "version": "2.0.0", "tasks": [ { "label": "build", "type": "shell", "command": "gcc", "args": [ "-g", "${file}", "-o", "${fileDirname}/${fileBasenameNoExtension}" ], "group": { "kind": "build", "isDefault": true } } ] }

9.2 多文件项目管理

合理组织项目目录结构:

project/ ├── include/ // 头文件 ├── src/ // 源文件 ├── lib/ // 第三方库 ├── build/ // 构建输出 └── Makefile // 构建脚本

头文件保护宏示例:

// utils.h #ifndef UTILS_H #define UTILS_H // 函数声明 int add(int a, int b); #endif

10. 性能优化技巧

10.1 编译器优化选项

GCC常用优化级别:

  • -O0:无优化(默认)
  • -O1:基本优化
  • -O2:推荐优化级别
  • -O3:激进优化
  • -Os:优化代码大小
gcc -O2 -o program program.c

10.2 算法优化实例

字符串拷贝优化对比:

// 普通实现 void strcpy1(char *dst, const char *src) { int i = 0; while((dst[i] = src[i]) != '\0') { i++; } } // 优化实现 void strcpy2(char *dst, const char *src) { while((*dst++ = *src++) != '\0'); }

实际测试中,优化版本在长字符串拷贝时性能提升明显。

11. 跨平台开发注意事项

11.1 数据类型可移植性

使用stdint.h中的明确长度类型:

#include <stdint.h> int32_t fixed32; // 固定32位有符号整数 uint64_t fixed64; // 固定64位无符号整数

11.2 字节序问题

网络编程中处理字节序转换:

#include <arpa/inet.h> uint32_t host = 0x12345678; uint32_t net = htonl(host); // 主机序转网络序 host = ntohl(net); // 网络序转主机序

12. 安全编程实践

12.1 缓冲区溢出防护

安全字符串函数使用:

#define _CRT_SECURE_NO_WARNINGS // Windows下禁用警告 char buf[10]; strncpy(buf, source, sizeof(buf)-1); buf[sizeof(buf)-1] = '\0'; // 确保终止

12.2 整数溢出检查

安全的整数运算:

#include <limits.h> int a = INT_MAX; int b = 1; if(a > INT_MAX - b) { // 处理溢出 } else { int c = a + b; }

13. 现代C语言特性

13.1 C11标准新特性

泛型选择表达式:

#define cbrt(X) _Generic((X), \ long double: cbrtl, \ default: cbrt, \ float: cbrtf)(X)

13.2 匿名结构体/联合体

简化嵌套数据结构:

struct person { char name[20]; struct { // 匿名结构体 int year; int month; int day; } birth; };

14. 测试驱动开发

14.1 单元测试框架

使用Unity测试框架示例:

#include "unity.h" void setUp(void) { // 初始化代码 } void tearDown(void) { // 清理代码 } void test_addition(void) { TEST_ASSERT_EQUAL(5, add(2, 3)); } int main(void) { UNITY_BEGIN(); RUN_TEST(test_addition); return UNITY_END(); }

14.2 测试覆盖率分析

GCC覆盖率检测:

gcc -fprofile-arcs -ftest-coverage program.c ./program gcov program.c

15. 嵌入式开发专项

15.1 寄存器操作模式

嵌入式开发中典型的寄存器操作:

#define GPIOA_MODER (*(volatile uint32_t*)0x40020000) // 设置PA5为输出模式 GPIOA_MODER &= ~(0x3 << (5*2)); // 清除原有设置 GPIOA_MODER |= (0x1 << (5*2)); // 设置为输出

15.2 中断服务例程

基本中断处理函数:

void __attribute__((interrupt)) TIM2_IRQHandler(void) { if(TIM2->SR & TIM_SR_UIF) { // 检查中断标志 // 处理中断 TIM2->SR &= ~TIM_SR_UIF; // 清除中断标志 } }

16. 代码风格与规范

16.1 Linux内核编码风格

主要特点:

  • 缩进使用8空格Tab
  • 函数返回值单独一行
  • 指针符号靠近变量名
int function_name(int arg1, char *arg2) { if (condition) { do_this(); do_that(); } return 0; }

16.2 防御性编程技巧

参数检查示例:

int safe_divide(int a, int b, int *result) { if(b == 0) { return -1; // 错误码 } if(result == NULL) { return -2; } *result = a / b; return 0; // 成功 }

17. 第三方库集成

17.1 使用CMake构建系统

基础CMakeLists.txt:

cmake_minimum_required(VERSION 3.10) project(MyProgram) set(CMAKE_C_STANDARD 11) add_executable(my_program src/main.c src/utils.c) target_include_directories(my_program PRIVATE include)

17.2 集成SQLite数据库

基本数据库操作:

#include <sqlite3.h> sqlite3 *db; if(sqlite3_open("test.db", &db) != SQLITE_OK) { fprintf(stderr, "无法打开数据库: %s\n", sqlite3_errmsg(db)); return; } char *err_msg = NULL; if(sqlite3_exec(db, "CREATE TABLE IF NOT EXISTS Users(ID INT, NAME TEXT);", NULL, NULL, &err_msg) != SQLITE_OK) { fprintf(stderr, "SQL错误: %s\n", err_msg); sqlite3_free(err_msg); } sqlite3_close(db);

18. 多线程编程

18.1 POSIX线程基础

创建线程示例:

#include <pthread.h> void *thread_func(void *arg) { int *val = (int*)arg; printf("线程收到值: %d\n", *val); return NULL; } int main() { pthread_t thread; int arg = 42; if(pthread_create(&thread, NULL, thread_func, &arg) != 0) { perror("线程创建失败"); return 1; } pthread_join(thread, NULL); return 0; }

18.2 线程同步机制

互斥锁使用:

pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER; int shared_data = 0; void *increment(void *arg) { for(int i = 0; i < 100000; i++) { pthread_mutex_lock(&mutex); shared_data++; pthread_mutex_unlock(&mutex); } return NULL; }

19. 网络编程基础

19.1 TCP客户端/服务端

基本TCP服务端:

#include <sys/socket.h> #include <netinet/in.h> int main() { int server_fd = socket(AF_INET, SOCK_STREAM, 0); struct sockaddr_in address; address.sin_family = AF_INET; address.sin_addr.s_addr = INADDR_ANY; address.sin_port = htons(8080); bind(server_fd, (struct sockaddr*)&address, sizeof(address)); listen(server_fd, 5); int client_fd = accept(server_fd, NULL, NULL); char buffer[1024] = {0}; read(client_fd, buffer, sizeof(buffer)); printf("收到: %s\n", buffer); close(client_fd); close(server_fd); return 0; }

19.2 UDP通信示例

UDP接收端:

int sock = socket(AF_INET, SOCK_DGRAM, 0); struct sockaddr_in servaddr; servaddr.sin_family = AF_INET; servaddr.sin_addr.s_addr = INADDR_ANY; servaddr.sin_port = htons(8080); bind(sock, (struct sockaddr*)&servaddr, sizeof(servaddr)); char buffer[1024]; struct sockaddr_in cliaddr; socklen_t len = sizeof(cliaddr); int n = recvfrom(sock, buffer, sizeof(buffer), 0, (struct sockaddr*)&cliaddr, &len); buffer[n] = '\0'; printf("收到: %s\n", buffer); close(sock);

20. 代码重构与优化

20.1 函数拆分原则

重构前的代码:

void process_data(char *input) { // 验证输入 if(strlen(input) > 100) { printf("输入过长"); return; } // 处理数据 for(int i = 0; input[i]; i++) { input[i] = toupper(input[i]); } // 输出结果 printf("结果: %s", input); }

重构后的代码:

int validate_input(const char *input) { return strlen(input) <= 100; } void transform_data(char *data) { for(int i = 0; data[i]; i++) { data[i] = toupper(data[i]); } } void process_data(char *input) { if(!validate_input(input)) { fprintf(stderr, "输入过长"); return; } transform_data(input); printf("结果: %s", input); }

20.2 性能热点分析

使用gprof进行性能分析:

gcc -pg program.c -o program ./program gprof program gmon.out > analysis.txt

分析输出示例:

Flat profile: Each sample counts as 0.01 seconds. % cumulative self self total time seconds seconds calls ms/call ms/call name 75.00 0.03 0.03 10000 0.00 0.00 sort 25.00 0.04 0.01 1 10.00 40.00 main

21. 调试与问题诊断

21.1 核心转储分析

生成和分析核心转储:

ulimit -c unlimited # 启用核心转储 ./program # 崩溃后生成core文件 gdb program core # 分析转储

21.2 日志系统实现

简易日志系统:

#include <stdarg.h> #define LOG_LEVEL_DEBUG 0 #define LOG_LEVEL_INFO 1 #define LOG_LEVEL_ERROR 2 void log_message(int level, const char *format, ...) { const char *level_str[] = {"DEBUG", "INFO", "ERROR"}; time_t now = time(NULL); char time_buf[20]; strftime(time_buf, sizeof(time_buf), "%Y-%m-%d %H:%M:%S", localtime(&now)); fprintf(stderr, "[%s] %s: ", time_buf, level_str[level]); va_list args; va_start(args, format); vfprintf(stderr, format, args); va_end(args); fprintf(stderr, "\n"); }

22. 工具链配置

22.1 静态代码分析

使用clang-tidy进行静态分析:

clang-tidy program.c --checks=* -- -std=c11

常见检查项:

  • bugprone-*
  • cert-*
  • clang-analyzer-*
  • misc-*

22.2 代码格式化

使用clang-format统一代码风格:

clang-format -i *.c *.h # 直接修改文件 clang-format --style=LLVM -dump-config > .clang-format # 生成配置文件

23. 跨语言交互

23.1 C调用Python

使用Python C API示例:

#include <Python.h> int main() { Py_Initialize(); PyObject *pModule = PyImport_ImportModule("math"); PyObject *pFunc = PyObject_GetAttrString(pModule, "sqrt"); PyObject *pArgs = PyTuple_Pack(1, PyFloat_FromDouble(2.0)); PyObject *pResult = PyObject_CallObject(pFunc, pArgs); double result = PyFloat_AsDouble(pResult); printf("√2 = %f\n", result); Py_Finalize(); return 0; }

23.2 Python调用C

使用ctypes模块:

from ctypes import CDLL, c_int lib = CDLL('./mylib.so') result = lib.add(c_int(2), c_int(3)) print(f"2 + 3 = {result}")

对应的C代码:

// mylib.c int add(int a, int b) { return a + b; }

编译为共享库:

gcc -shared -fPIC -o mylib.so mylib.c

24. 图形界面开发

24.1 GTK基础程序

简单GTK窗口示例:

#include <gtk/gtk.h> static void on_activate(GtkApplication *app) { GtkWidget *window = gtk_application_window_new(app); gtk_window_set_title(GTK_WINDOW(window), "C语言GTK示例"); gtk_window_set_default_size(GTK_WINDOW(window), 400, 300); GtkWidget *button = gtk_button_new_with_label("点击我"); gtk_window_set_child(GTK_WINDOW(window), button); gtk_widget_show(window); } int main(int argc, char **argv) { GtkApplication *app = gtk_application_new("org.example.app", G_APPLICATION_DEFAULT_FLAGS); g_signal_connect(app, "activate", G_CALLBACK(on_activate), NULL); int status = g_application_run(G_APPLICATION(app), argc, argv); g_object_unref(app); return status; }

编译命令:

gcc `pkg-config --cflags gtk4` program.c `pkg-config --libs gtk4` -o program

24.2 简单绘图程序

使用Cairo绘图:

#include <cairo/cairo.h> int main() { cairo_surface_t *surface = cairo_image_surface_create(CAIRO_FORMAT_ARGB32, 400, 300); cairo_t *cr = cairo_create(surface); // 设置白色背景 cairo_set_source_rgb(cr, 1, 1, 1); cairo_paint(cr); // 绘制红色矩形 cairo_set_source_rgb(cr, 1, 0, 0); cairo_rectangle(cr, 100, 100, 200, 100); cairo_fill(cr); // 保存为PNG cairo_surface_write_to_png(surface, "output.png"); cairo_destroy(cr); cairo_surface_destroy(surface); return 0; }

25. 嵌入式数据库应用

25.1 SQLite内存数据库

创建内存数据库示例:

#include <sqlite3.h> #include <stdio.h> int main() { sqlite3 *db; if(sqlite3_open(":memory:", &db) != SQLITE_OK) { fprintf(stderr, "无法打开数据库: %s\n", sqlite3_errmsg(db)); return 1; } char *err_msg = NULL; const char *sql = "CREATE TABLE Test(ID INT, Name TEXT);" "INSERT INTO Test VALUES(1, 'Alice');" "INSERT INTO Test VALUES(2, 'Bob');"; if(sqlite3_exec(db, sql, NULL, NULL, &err_msg) != SQLITE_OK) { fprintf(stderr, "SQL错误: %s\n", err_msg); sqlite3_free(err_msg); } sqlite3_close(db); return 0; }

25.2 数据库查询优化

使用预处理语句提高性能:

sqlite3_stmt *stmt; const char *sql = "SELECT * FROM Users WHERE age > ?;"; if(sqlite3_prepare_v2(db, sql, -1, &stmt, NULL) != SQLITE_OK) { fprintf(stderr, "准备语句失败: %s\n", sqlite3_errmsg(db)); return; } int min_age = 18; sqlite3_bind_int(stmt, 1, min_age); while(sqlite3_step(stmt) == SQLITE_ROW) { int id = sqlite3_column_int(stmt, 0); const char *name = (const char*)sqlite3_column_text(stmt, 1); printf("ID: %d, Name: %s\n", id, name); } sqlite3_finalize(stmt);

26. 正则表达式处理

26.1 POSIX正则表达式

基本正则匹配示例:

#include <regex.h> #include <stdio.h> int main() { regex_t regex; int ret; ret = regcomp(&regex, "^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\\.[a-zA-Z]{2,}$", REG_EXTENDED); if(ret) { fprintf(stderr, "无法编译正则表达式\n"); return 1; } ret = regexec(&regex, "test@example.com", 0, NULL, 0); if(!ret) { printf("匹配成功\n"); } else if(ret == REG_NOMATCH) { printf("不匹配\n"); } else { char msgbuf[100]; regerror(ret, &regex, msgbuf, sizeof(msgbuf)); fprintf(stderr, "匹配失败: %s\n", msgbuf); } regfree(&regex); return 0; }

26.2 PCRE库使用

更强大的PCRE库示例:

#include <pcre.h> #include <stdio.h> int main() { const char *pattern = "(\\d{4})-(\\d{2})-(\\d{2})"; const char *subject = "日期: 2023-05-15"; pcre *re; const char *error; int erroffset; re = pcre_compile(pattern, 0, &error, &erroffset, NULL); if(!re) { fprintf(stderr, "编译错误: %s\n", error); return 1; } int ovector[30]; int rc = pcre_exec(re, NULL, subject, strlen(subject), 0, 0, ovector, 30); if(rc >= 0) { printf("匹配成功\n"); for(int i = 0; i < rc; i++) { const char *substring = subject + ovector[2*i]; int length = ovector[2*i+1] - ovector[2*i]; printf("匹配组 %d: %.*s\n", i, length, substring); } } else { printf("未找到匹配\n"); } pcre_free(re); return 0; }

27. 日期时间处理

27.1 时间转换与格式化

获取和格式化当前时间:

#include <time.h> #include <stdio.h> int main() { time_t now = time(NULL); struct tm *local = localtime(&now); char buf[80]; strftime(buf, sizeof(buf), "%Y-%m-%d %H:%M:%S", local); printf("当前时间: %s\n", buf); // 计算7天后的日期 time_t future = now + 7 * 24 * 60 * 60; local = localtime(&future); strftime(buf, sizeof(buf), "%Y-%m-%d", local); printf("7天后日期: %s\n", buf); return 0; }

27.2 高精度计时

测量代码执行时间:

#include <time.h> #include <stdio.h> int main() { struct timespec start, end; clock_gettime(CLOCK_MONOTONIC, &start); // 要测量的代码 volatile double sum = 0; for(int i = 0; i < 1000000; i++) { sum += i * 0.1; } clock_gettime(CLOCK_MONOTONIC, &end); double elapsed = (end.tv_sec - start.tv_sec) + (end.tv_nsec - start.tv_nsec) / 1e9; printf("耗时: %.6f 秒\n", elapsed); return 0; }

28. 数学计算与科学计算

28.1 数值积分实现

梯形法数值积分:

#include <math.h> #include <stdio.h> double f(double x) { return sin(x); // 被积函数 } double trapezoidal(double a, double b, int n) { double h = (b - a) / n; double sum = (f(a) + f(b)) / 2.0; for(int i = 1; i < n; i++) { sum += f(a + i * h); } return sum * h; } int main() { double a = 0, b = M_PI; int n = 1000; double result = trapezoidal(a, b, n); printf("∫sin(x)dx从0到π ≈ %.10f\n", result); return 0; }

28.2 线性代数计算

使用GSL库进行矩阵运算:

#include <gsl/gsl_matrix.h> #include <gsl/gsl_linalg.h> #include <stdio.h> int main() { gsl_matrix *A = gsl_matrix_alloc(3, 3); gsl_matrix_set(A, 0, 0, 1.0); gsl_matrix_set(A, 0, 1, 2.0); gsl_matrix_set(A, 0, 2, 3.0); gsl_matrix_set(A, 1, 0, 4.0); gsl_matrix_set(A, 1, 1, 5.0); gsl_matrix_set(A, 1, 2, 6.0); gsl_matrix_set(A, 2, 0, 7.0); gsl_matrix_set(A, 2, 1, 8.0); gsl_matrix_set(A, 2, 2, 10.0); gsl_vector *b = gsl_vector_alloc(3); gsl_vector_set(b, 0, 3.0); gsl_vector_set(b, 1, 6.0); gsl_vector_set(b, 2, 9.0); gsl_vector *x = gsl_vector_alloc(3); gsl_permutation *p = gsl_permutation_alloc(3); int signum; gsl_linalg_LU_decomp(A, p, &signum); gsl_linalg_LU_solve(A, p, b, x); printf("解: x = %g, y = %g, z = %g\n", gsl_vector_get(x, 0), gsl_vector_get(x, 1), gsl_vector_get(x, 2)); gsl_matrix_free(A); gsl_vector_free(b); gsl_vector_free(x); gsl_permutation_free(p); return 0; }

29. 密码学基础

29.1 哈希算法实现

使用OpenSSL计算SHA256:

#include <openssl/sha.h> #include <stdio.h> #include <string.h> void print_hex(const unsigned char *data, size_t len) { for(size_t i = 0; i < len; i++) { printf("%02x", data[i]); } printf("\n"); } int main() { const char *input = "Hello, world!"; unsigned char hash[SHA256_DIGEST_LENGTH]; SHA256((const unsigned char*)input, strlen(input), hash); printf("SHA256(\"%s\") = ", input); print_hex(hash, SHA256_DIGEST_LENGTH); return 0; }

29.2 AES加密示例

使用OpenSSL进行AES加密:

#include <openssl/aes.h> #include <stdio.h> #include <string.h> void print_hex(const unsigned char *data, size_t len) { for(size_t i = 0; i < len; i++) { printf("%02x", data[i]); } printf("\n"); } int main() { const char *plaintext = "Secret message"; const char *key = "0123456789abcdef"; // 16字节密钥 unsigned char iv[AES_BLOCK_SIZE]; memset(iv, 0x00, sizeof(iv)); // 初始化向量 AES_KEY aes_key; AES_set_encrypt_key((const unsigned char*)key, 128, &aes_key); size_t len = strlen(plaintext); size_t padded_len = ((len + AES_BLOCK_SIZE) / AES_BLOCK_SIZE) * AES_BLOCK_SIZE; unsigned char ciphertext[padded_len]; memset(ciphertext, 0, sizeof(ciphertext)); AES_cbc_encrypt((const unsigned char*)plaintext, ciphertext, len, &aes_key, iv, AES_ENCRYPT); printf("明文: %s\n", plaintext); printf("密文: "); print_hex(ciphertext
版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/9/15 9:13:15

3步搞定太原网站建设优化,一文搞懂避坑指南

3步搞定太原网站建设优化,一文搞懂避坑指南 模板网站太丑不够用,这是很多太原企业主做官网时遇到的第一个坎。刚建好的站,看着像十年前的风格,客户点进来三秒就关掉,流量全白费。想改吧,又不知道从哪下手,怕花钱请人优化被坑,怕自己折腾半天没效果。…

作者头像 李华
网站建设 2026/9/15 9:09:12

Python内置数据类型详解与使用技巧

1. Python内置数据类型概览Python作为一门动态类型语言&#xff0c;其内置数据类型系统设计精巧且功能强大。与静态类型语言不同&#xff0c;Python变量不需要预先声明类型&#xff0c;而是在运行时根据赋值自动确定数据类型。这种特性使得Python代码编写更加灵活&#xff0c;但…

作者头像 李华
网站建设 2026/9/15 9:08:29

柬埔寨商标已经完成后,别人还能提出异议、撤销或无效吗?

小编结合柬埔寨商标制度的一般规则和跨境品牌维护经验判断&#xff0c;商标完成注册并不等于权利永久稳定。企业容易忽略的是&#xff0c;注册后仍可能面对异议、撤销、无效争议&#xff0c;以及因未使用、信息不一致或续展遗漏产生的权利风险。 实际操作中&#xff0c;很多争议…

作者头像 李华
网站建设 2026/9/15 9:08:26

ReferTrack——“先认出,再跟随”的智能跟随方法:基于 Refer-CoT(决定跟谁)、与TVBI(把选择结果写进记忆里)的单目具身视觉跟踪

前言 关于智能跟随&#xff0c;一直是机器人的一个重要课题&#xff0c;本博客中之前也解读过类似的框架&#xff0c;比如 TrackVLA与其plus升级版——开放世界下的四足具身视觉跟踪EVT(智能跟随)&#xff1a;集目标识别与轨迹规划为一体的VLA&#xff0c;不怕高动态与遮挡Un…

作者头像 李华
网站建设 2026/9/15 9:08:21

DeepSeek V4.1实测:API接入、本地部署与高频报错排查指南

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

作者头像 李华
网站建设 2026/9/15 9:07:11

12-JVM 调优方法论与参数速查

本篇是「JVM 与性能调优系列」第 12 篇&#xff0c;系列收尾。前面 11 篇你都看了&#xff0c;但真到线上还是乱。因为缺一套「先想清楚再动手」的方法论。这篇把 JVM 调优收成一张图、一张表&#xff0c;以后遇事照着走。一、调优的第一原则&#xff1a;别调优 听起来反直觉&a…

作者头像 李华