C语言入门指南:从核心概念到实战项目,掌握指针与内存管理

news2026/5/17 16:03:28
1. 项目概述一份写给新手的C语言全景地图“长文预警比较全面的C语言入门笔记”——这个标题背后是一位老码农比如我在某个深夜面对无数初学者在C语言入门路上反复踩坑、四处寻找零散资料时决定整理一份“一站式”学习指南的冲动。C语言作为计算机世界的“母语”其重要性无需多言。它不仅是操作系统、嵌入式系统、数据库等底层核心的基石更是理解计算机如何工作的最佳窗口。然而它的“入门”却常常伴随着指针的困惑、内存的泄漏和段错误的恐惧。这份笔记的目标就是为你绘制一张清晰、全面的C语言入门地图。它不追求成为一本包罗万象的百科全书而是聚焦于一个核心目标让一个零基础或稍有接触的初学者能够建立起对C语言核心概念的正确认知并具备动手编写、调试简单程序的能力。它适合那些刚刚踏入计算机科学大门的学生、希望夯实基础的转行者或是任何对“机器如何执行代码”抱有好奇心的爱好者。接下来的内容我会以一个过来人的视角带你从最基础的“Hello, World!”开始一步步深入到内存、指针、函数这些核心地带并分享那些只有踩过坑才知道的实操心得和避雷指南。2. 学习路径与核心思想拆解2.1 为什么从C开始理解“贴近机器”的本质很多新手会问Python、JavaScript看起来更简单、更酷为什么还要学“古老”的C语言我的回答是C语言教你的是“规则”而高级语言为你提供了“便利”。学习C语言就像学开车先学手动挡。你不仅要知道踩油门车会走还要知道离合器如何结合、变速箱如何换挡。这个过程让你深刻理解车辆的运行机制以后开自动挡高级语言时你才能更好地应对突发状况。C语言的“贴近机器”体现在几个方面直接的内存操作指针、明确的类型系统、极简的运行时库。在Python里你创建一个列表无需关心它占用了多少内存、存放在哪里。但在C语言里你需要用malloc申请内存用free释放并时刻警惕访问越界。这种“操心”正是理解计算机内存模型的最佳训练。当你理解了数组名本质上是一个指向首元素的常量指针你就能明白为什么高级语言里的“引用”和“值传递”有那样的行为。这份笔记会贯穿这一思想每一个语法特性都尝试关联到它在机器层面的实际表现。2.2 构建知识体系的四层结构一份全面的笔记不能是知识点的简单罗列。我将其构建为一个四层结构确保学习是循序渐进、有机关联的基础语法层变量、数据类型、运算符、流程控制分支与循环。这是语言的“单词”和“简单句型”。重点在于建立类型意识理解int,float,char在内存中的不同形态以及if-else,for,while如何控制执行流。核心机制层函数、数组、指针。这是C语言的“灵魂”。函数是代码复用的单元数组是数据的线性集合而指针是访问内存的“地址”。这一层是新手到入门的关键跨越笔记会花费大量篇幅用图解和类比来化解指针的抽象性。复合结构层结构体、联合体、枚举。这是创建自定义复杂类型的工具。结构体让你能把相关的数据打包在一起如一个学生的学号、姓名、成绩模拟现实世界的实体。理解它们的内存对齐规则对写出高效、正确的代码至关重要。系统交互与进阶层预处理、文件I/O、动态内存管理。这是让程序“活”起来能与操作系统和硬件资源交互的部分。#include,#define这些预处理指令在编译前做了什么如何安全地读写文件malloc/free的正确姿势是什么如何避免内存泄漏这是从“写小程序”到“写实用程序”的必经之路。这个结构确保了你在学习时始终知道当前内容在整个体系中的位置以及它为何重要。3. 核心细节解析与避坑指南3.1 指针从“地址”到“间接访问”的思维转换指针是C语言最强大也最令人困惑的特性。新手常犯的错误是试图一次性理解所有关于指针的复杂概念。我的建议是分三步走第一步建立“地址”的物理概念。把计算机内存想象成一排带编号的邮箱地址。变量int a 10;就是把值10放进某个邮箱比如编号0x7ffeeda12b58。a取地址运算符就是获取这个邮箱的编号。指针变量int *p;本身也是一个邮箱但它里面存放的不是普通数据而是另一个邮箱的编号。p a;就是把a的邮箱编号写进p这个邮箱里。第二步理解“解引用”就是“按图索骥”。*p解引用运算符的意思是请打开p这个邮箱取出里面的编号地址然后去找到那个编号对应的邮箱操作里面的值。所以*p 20;就相当于把20写入了a所在的邮箱从而改变了a的值。第三步区分“指针的类型”。int *p、char *p、double *p这些类型声明主要告诉编译器两件事一是当我对指针进行p指针算术时应该移动多少个字节int通常4字节char1字节二是我用*p取出的数据应该如何解释按整数、字符还是浮点数格式。这是避免访问错乱和算术错误的关键。避坑心得永远在定义指针时初始化。int *p;后直接使用*p是未定义行为可能导致程序崩溃。要么初始化为NULLint *p NULL;要么立即让它指向有效的内存地址。在解引用前务必检查指针是否为NULL。3.2 数组与指针的暧昧关系“数组名就是指向其首元素的指针常量”这句话对了一半。更准确地说在大多数表达式中如函数传参、赋值给指针数组名会退化成指向其首元素的指针。但有两个重要例外sizeof(数组名)返回的是整个数组占用的字节数而不是指针的大小。数组名得到的是指向整个数组的指针其类型是int (*)[N]与int *不同进行指针运算时跨度是整个数组。函数传参的陷阱当你将数组传递给函数时例如void func(int arr[])实际上传递的是指针。因此在函数内部无法用sizeof(arr)得到数组长度。常见的做法是额外传递一个长度参数void func(int arr[], int len)。这也是为什么在函数内修改数组元素会影响到原数组的原因——它们操作的是同一块内存。3.3 内存管理栈、堆与静态区的生死簿理解内存区域是写出健壮程序的基础。栈Stack由编译器自动分配释放存放局部变量、函数参数等。速度快但空间有限。函数返回后其栈帧被回收局部变量失效。绝对不要返回指向局部变量的指针堆Heap由程序员手动管理malloc/calloc/realloc/free。空间大生命周期由程序员控制。这是动态数据结构的舞台如链表、树。记住有malloc就必须有对应的free且只能free一次。静态/全局区存放全局变量和静态变量static。在程序启动时分配结束时释放。默认初始化为零值。实操技巧对于动态内存养成“申请-检查-使用-释放”的固定流程。int *p (int*)malloc(10 * sizeof(int));之后立刻检查if (p NULL) { /* 处理错误 */ }。使用完毕free(p);并最好将p NULL;防止“野指针”。4. 从零到一的完整项目实操构建一个简易通讯录理论需要实践来巩固。让我们通过一个命令行下的简易通讯录程序串联起核心知识点。这个程序将实现添加、查看、搜索、删除联系人的功能。4.1 项目设计与数据结构定义首先我们需要一个结构体来代表一个联系人。// contact.h #ifndef CONTACT_H #define CONTACT_H #define MAX_NAME_LEN 50 #define MAX_PHONE_LEN 15 #define MAX_EMAIL_LEN 50 #define INIT_CAPACITY 5 // 初始容量 #define GROWTH_FACTOR 2 // 扩容因子 typedef struct { int id; // 唯一标识 char name[MAX_NAME_LEN]; char phone[MAX_PHONE_LEN]; char email[MAX_EMAIL_LEN]; } Contact; typedef struct { Contact *contacts; // 指向动态数组的指针 int size; // 当前联系人数量 int capacity; // 当前动态数组容量 } ContactBook; // 函数声明 ContactBook* create_contact_book(); void destroy_contact_book(ContactBook *book); int add_contact(ContactBook *book, const char *name, const char *phone, const char *email); void display_all(const ContactBook *book); Contact* find_contact_by_name(const ContactBook *book, const char *name); int delete_contact_by_id(ContactBook *book, int id); int save_to_file(const ContactBook *book, const char *filename); int load_from_file(ContactBook *book, const char *filename); #endif设计解析我们没有使用固定大小的数组Contact contacts[100];而是采用了动态数组。ContactBook结构体包含一个指针*contacts指向堆上分配的内存。size记录有效数据量capacity记录当前分配的总容量。当size capacity时我们需要使用realloc进行扩容。这种设计更灵活能适应任意数量的联系人。4.2 核心功能实现动态内存与文件I/O接下来是实现核心的create,add,save/load函数。// contact.c #include stdio.h #include stdlib.h #include string.h #include contact.h ContactBook* create_contact_book() { ContactBook *book (ContactBook*)malloc(sizeof(ContactBook)); if (!book) return NULL; book-contacts (Contact*)malloc(INIT_CAPACITY * sizeof(Contact)); if (!book-contacts) { free(book); return NULL; } book-size 0; book-capacity INIT_CAPACITY; return book; } void destroy_contact_book(ContactBook *book) { if (book) { free(book-contacts); // 先释放内部数组 free(book); // 再释放结构体本身 } } int add_contact(ContactBook *book, const char *name, const char *phone, const char *email) { // 1. 检查容量必要时扩容 if (book-size book-capacity) { int new_capacity book-capacity * GROWTH_FACTOR; Contact *new_contacts (Contact*)realloc(book-contacts, new_capacity * sizeof(Contact)); if (!new_contacts) { return -1; // 扩容失败 } book-contacts new_contacts; book-capacity new_capacity; printf(通讯录已扩容至 %d 条容量。\n, new_capacity); } // 2. 添加新联系人 Contact *new (book-contacts[book-size]); new-id book-size 1; // 简单自增ID strncpy(new-name, name, MAX_NAME_LEN - 1); new-name[MAX_NAME_LEN - 1] \0; // 确保字符串终止 strncpy(new-phone, phone, MAX_PHONE_LEN - 1); new-phone[MAX_PHONE_LEN - 1] \0; strncpy(new-email, email, MAX_EMAIL_LEN - 1); new-email[MAX_EMAIL_LEN - 1] \0; book-size; return new-id; // 返回新联系人的ID } int save_to_file(const ContactBook *book, const char *filename) { FILE *fp fopen(filename, wb); // 二进制写入 if (!fp) return -1; // 先写入当前联系人数量 fwrite((book-size), sizeof(int), 1, fp); // 再写入所有联系人数据 fwrite(book-contacts, sizeof(Contact), book-size, fp); fclose(fp); return 0; } int load_from_file(ContactBook *book, const char *filename) { FILE *fp fopen(filename, rb); if (!fp) return -1; int file_size; fread(file_size, sizeof(int), 1, fp); // 确保容量足够 if (file_size book-capacity) { Contact *new_contacts (Contact*)realloc(book-contacts, file_size * sizeof(Contact)); if (!new_contacts) { fclose(fp); return -1; } book-contacts new_contacts; book-capacity file_size; } fread(book-contacts, sizeof(Contact), file_size, fp); book-size file_size; fclose(fp); return 0; }关键点解析realloc的使用realloc可能返回一个新的内存地址。因此我们使用一个临时指针new_contacts接收返回值检查成功后再赋给book-contacts。直接book-contacts realloc(...)是危险的因为如果失败返回NULL原指针就丢失了导致内存泄漏。字符串安全拷贝使用strncpy并手动设置终止符\0是防止缓冲区溢出的良好习惯。二进制文件I/O我们使用wb和rb模式进行二进制读写。先写入size再写入整个contacts数组。这种方式读写效率高但文件内容不可直接阅读非文本格式。注意fwrite/fread的参数顺序(数据指针, 单个元素大小, 元素个数, 文件指针)。4.3 主程序与用户交互最后编写一个简单的主程序main.c来驱动整个系统。// main.c #include stdio.h #include string.h #include contact.h void print_menu() { printf(\n 简易通讯录 \n); printf(1. 添加联系人\n); printf(2. 显示所有联系人\n); printf(3. 查找联系人\n); printf(4. 删除联系人\n); printf(5. 保存到文件\n); printf(6. 从文件加载\n); printf(0. 退出\n); printf(请选择: ); } int main() { ContactBook *book create_contact_book(); if (!book) { printf(初始化通讯录失败\n); return 1; } int choice; char name[MAX_NAME_LEN], phone[MAX_PHONE_LEN], email[MAX_EMAIL_LEN]; int id; do { print_menu(); scanf(%d, choice); getchar(); // 吸收回车符避免影响后续fgets switch (choice) { case 1: printf(请输入姓名: ); fgets(name, MAX_NAME_LEN, stdin); name[strcspn(name, \n)] \0; // 去除末尾换行符 printf(请输入电话: ); fgets(phone, MAX_PHONE_LEN, stdin); phone[strcspn(phone, \n)] \0; printf(请输入邮箱: ); fgets(email, MAX_EMAIL_LEN, stdin); email[strcspn(email, \n)] \0; id add_contact(book, name, phone, email); if (id 0) printf(添加成功ID: %d\n, id); else printf(添加失败\n); break; case 2: display_all(book); break; case 3: printf(请输入要查找的姓名: ); fgets(name, MAX_NAME_LEN, stdin); name[strcspn(name, \n)] \0; Contact *found find_contact_by_name(book, name); if (found) { printf(找到: ID:%d, 姓名:%s, 电话:%s, 邮箱:%s\n, found-id, found-name, found-phone, found-email); } else { printf(未找到联系人。\n); } break; case 4: printf(请输入要删除的联系人ID: ); scanf(%d, id); if (delete_contact_by_id(book, id) 0) { printf(删除成功。\n); } else { printf(删除失败ID可能不存在。\n); } break; case 5: if (save_to_file(book, contacts.dat) 0) { printf(保存成功。\n); } else { printf(保存失败。\n); } break; case 6: if (load_from_file(book, contacts.dat) 0) { printf(加载成功共 %d 条记录。\n, book-size); } else { printf(加载失败或文件不存在。\n); } break; case 0: printf(再见\n); break; default: printf(无效选择请重新输入。\n); } } while (choice ! 0); destroy_contact_book(book); return 0; }交互细节注意scanf和fgets混用的问题。scanf(%d, choice)读取整数后会在输入缓冲区留下一个换行符\n。紧接着的fgets会立刻读到这个\n从而认为输入结束。我们用getchar()来“吃掉”这个多余的换行符。strcspn(name, \n)函数用于找到字符串中第一个\n的位置然后将其替换为\0这是处理fgets读取字符串包含换行符的常用技巧。5. 编译、调试与进阶思考5.1 多文件编译与Makefile我们的项目现在分成了contact.h,contact.c,main.c三个文件。如何编译呢gcc -c contact.c -o contact.o gcc -c main.c -o main.o gcc contact.o main.o -o addressbook-c参数表示只编译不链接生成目标文件.o。最后一步将两个目标文件链接成可执行文件addressbook。对于更复杂的项目手动输入命令很麻烦。我们可以写一个简单的MakefileCC gcc CFLAGS -Wall -g # 开启所有警告和调试信息 TARGET addressbook OBJS contact.o main.o all: $(TARGET) $(TARGET): $(OBJS) $(CC) $(OBJS) -o $(TARGET) contact.o: contact.c contact.h $(CC) $(CFLAGS) -c contact.c main.o: main.c contact.h $(CC) $(CFLAGS) -c main.c clean: rm -f $(OBJS) $(TARGET) .PHONY: all clean在终端执行make就会自动编译make clean清理生成的文件。-Wall和-g是给新手的强烈建议前者帮你发现很多潜在问题后者为调试器gdb生成符号信息。5.2 使用GDB进行基础调试程序崩溃段错误是C语言初学者的常客。这时就需要调试器。假设我们的程序addressbook在某个操作后崩溃。启动GDBgdb ./addressbook运行程序在gdb提示符下输入run。程序崩溃后gdb会停在出错的位置。输入backtrace或bt查看函数调用栈定位问题发生在哪个函数的哪一行。查看变量使用print 变量名或p查看变量的当前值。这对于检查指针是否为NULL、数组索引是否越界非常有帮助。设置断点在怀疑有问题的函数或行号设置断点例如break add_contact或break contact.c:50。然后run程序会在断点处暂停你可以一步步next单步跳过或step单步进入执行。调试心得大部分段错误都源于两点解引用非法指针包括NULL指针、已释放的指针、指向局部变量的指针和数组访问越界。遇到崩溃先检查这两点。5.3 项目可能的扩展方向这个简易通讯录只是一个起点你可以通过扩展它来深入学习链表版通讯录将动态数组替换为链表。这需要你定义ContactNode结构体包含Contact数据和指向下一个节点的指针next。实现链表的插入、删除、遍历。这能让你深刻理解指针的“链接”能力。按姓名排序实现一个排序函数如冒泡排序或快速排序按联系人的姓名进行排序。你需要比较字符串strcmp并交换结构体数据或调整指针。更复杂的查找实现按电话号码部分匹配、按邮箱域名查找等功能。错误处理强化当前很多函数返回简单的-1表示失败。可以定义一套错误码枚举让错误信息更精确。使用更安全的内存函数了解并尝试使用strncpy_sC11 Annex K等更安全的字符串函数如果编译器支持。6. 常见问题与排查技巧实录即使理解了所有概念实际编码时依然会遇到各种“诡异”的问题。这里记录一些高频问题和我的排查思路。6.1 程序运行一切正常但退出时崩溃现象程序功能都正确但在main函数结束return 0;时或者关闭时突然崩溃。可能原因与排查内存越界写入这是最常见的原因。你可能在某个数组的边界之外之前或之后写入了数据破坏了堆或栈的管理信息如malloc的元数据。当程序最后调用free或清理栈时这些被破坏的数据导致崩溃。排查工具使用ValgrindLinux/macOS或Dr. MemoryWindows。在终端运行valgrind ./your_program它会详细报告非法读/写、使用未初始化内存、内存泄漏等问题。这是C/C程序员必备的神器。重复释放对同一块内存调用了两次free。返回指向局部变量的指针函数内定义的局部数组将其地址返回给调用者。函数返回后该内存已失效后续访问导致未定义行为。6.2scanf读取字符串时的缓冲区陷阱现象使用scanf(“%s”, buf)读取字符串后后续的scanf或fgets行为异常。原因scanf(“%s”)会读取直到遇到空白字符空格、制表符、换行但它会把换行符留在输入缓冲区。下一个输入函数会立刻读到这个换行符。解决方案使用fgets替代fgets(buf, size, stdin)会读取一行包括换行符更安全可控。记得处理末尾的\n。清空缓冲区在scanf(“%s”)后使用while(getchar() ! ‘\n’);来清空缓冲区直到换行符。但注意如果输入本身就有问题这种方法可能不完美。最佳实践对于交互式程序的字符串输入我强烈推荐统一使用fgets然后在需要时用sscanf从读取的字符串中解析其他类型的数据。6.3 头文件重复包含与条件编译现象编译时出现“重复定义”的错误尤其是在多个.c文件包含了同一个头文件且该头文件里定义了变量或函数时。原因一个头文件在同一个编译单元中被包含了多次。标准解决方案在每个头文件的开头和结尾使用“包含守卫”。// myheader.h #ifndef MYHEADER_H // 如果MYHEADER_H这个宏没有被定义过 #define MYHEADER_H // 那么就定义它 // 头文件的实际内容声明、宏定义等 #endif // MYHEADER_H这样即使多个文件#include “myheader.h”在第一次包含后MYHEADER_H就被定义了后续的包含会因为#ifndef条件为假而被跳过。这是编写头文件的铁律。6.4 指针导致的“悬空引用”与“野指针”悬空引用指针指向的内存已经被释放free了但指针变量本身还在继续使用它。野指针指针变量未初始化或free后未置NULL其值是随机的垃圾地址。后果解引用它们会导致不可预知的行为从读取到垃圾数据到程序崩溃。防御性编程初始化定义指针时立即初始化为NULL。int *p NULL;检查在解引用指针*p或传递给可能解引用的函数前检查是否为NULL。置空free(p);之后立刻p NULL;。这样即使再次free(p)因为free(NULL)是安全的或误用也容易发现问题。学习C语言就像学习一门严谨的手艺。它不提供过多的保护迫使你直面计算机的运作细节。这个过程初期充满挑战但一旦你跨过那道坎建立起清晰的内存模型和系统思维再去学习任何其他高级语言都会有一种“降维打击”的通透感。这份笔记希望能成为你跨越那道坎的一块垫脚石。记住多写、多调、多思考每一个编译错误和运行时崩溃都是你理解更深层原理的机会。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2618500.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

SpringBoot-17-MyBatis动态SQL标签之常用标签

文章目录 1 代码1.1 实体User.java1.2 接口UserMapper.java1.3 映射UserMapper.xml1.3.1 标签if1.3.2 标签if和where1.3.3 标签choose和when和otherwise1.4 UserController.java2 常用动态SQL标签2.1 标签set2.1.1 UserMapper.java2.1.2 UserMapper.xml2.1.3 UserController.ja…

wordpress后台更新后 前端没变化的解决方法

使用siteground主机的wordpress网站,会出现更新了网站内容和修改了php模板文件、js文件、css文件、图片文件后,网站没有变化的情况。 不熟悉siteground主机的新手,遇到这个问题,就很抓狂,明明是哪都没操作错误&#x…

网络编程(Modbus进阶)

思维导图 Modbus RTU(先学一点理论) 概念 Modbus RTU 是工业自动化领域 最广泛应用的串行通信协议,由 Modicon 公司(现施耐德电气)于 1979 年推出。它以 高效率、强健性、易实现的特点成为工业控制系统的通信标准。 包…

UE5 学习系列(二)用户操作界面及介绍

这篇博客是 UE5 学习系列博客的第二篇,在第一篇的基础上展开这篇内容。博客参考的 B 站视频资料和第一篇的链接如下: 【Note】:如果你已经完成安装等操作,可以只执行第一篇博客中 2. 新建一个空白游戏项目 章节操作,重…

IDEA运行Tomcat出现乱码问题解决汇总

最近正值期末周,有很多同学在写期末Java web作业时,运行tomcat出现乱码问题,经过多次解决与研究,我做了如下整理: 原因: IDEA本身编码与tomcat的编码与Windows编码不同导致,Windows 系统控制台…

利用最小二乘法找圆心和半径

#include <iostream> #include <vector> #include <cmath> #include <Eigen/Dense> // 需安装Eigen库用于矩阵运算 // 定义点结构 struct Point { double x, y; Point(double x_, double y_) : x(x_), y(y_) {} }; // 最小二乘法求圆心和半径 …

使用docker在3台服务器上搭建基于redis 6.x的一主两从三台均是哨兵模式

一、环境及版本说明 如果服务器已经安装了docker,则忽略此步骤,如果没有安装,则可以按照一下方式安装: 1. 在线安装(有互联网环境): 请看我这篇文章 传送阵>> 点我查看 2. 离线安装(内网环境):请看我这篇文章 传送阵>> 点我查看 说明&#xff1a;假设每台服务器已…

XML Group端口详解

在XML数据映射过程中&#xff0c;经常需要对数据进行分组聚合操作。例如&#xff0c;当处理包含多个物料明细的XML文件时&#xff0c;可能需要将相同物料号的明细归为一组&#xff0c;或对相同物料号的数量进行求和计算。传统实现方式通常需要编写脚本代码&#xff0c;增加了开…

LBE-LEX系列工业语音播放器|预警播报器|喇叭蜂鸣器的上位机配置操作说明

LBE-LEX系列工业语音播放器|预警播报器|喇叭蜂鸣器专为工业环境精心打造&#xff0c;完美适配AGV和无人叉车。同时&#xff0c;集成以太网与语音合成技术&#xff0c;为各类高级系统&#xff08;如MES、调度系统、库位管理、立库等&#xff09;提供高效便捷的语音交互体验。 L…

(LeetCode 每日一题) 3442. 奇偶频次间的最大差值 I (哈希、字符串)

题目&#xff1a;3442. 奇偶频次间的最大差值 I 思路 &#xff1a;哈希&#xff0c;时间复杂度0(n)。 用哈希表来记录每个字符串中字符的分布情况&#xff0c;哈希表这里用数组即可实现。 C版本&#xff1a; class Solution { public:int maxDifference(string s) {int a[26]…

【大模型RAG】拍照搜题技术架构速览:三层管道、两级检索、兜底大模型

摘要 拍照搜题系统采用“三层管道&#xff08;多模态 OCR → 语义检索 → 答案渲染&#xff09;、两级检索&#xff08;倒排 BM25 向量 HNSW&#xff09;并以大语言模型兜底”的整体框架&#xff1a; 多模态 OCR 层 将题目图片经过超分、去噪、倾斜校正后&#xff0c;分别用…

【Axure高保真原型】引导弹窗

今天和大家中分享引导弹窗的原型模板&#xff0c;载入页面后&#xff0c;会显示引导弹窗&#xff0c;适用于引导用户使用页面&#xff0c;点击完成后&#xff0c;会显示下一个引导弹窗&#xff0c;直至最后一个引导弹窗完成后进入首页。具体效果可以点击下方视频观看或打开下方…

接口测试中缓存处理策略

在接口测试中&#xff0c;缓存处理策略是一个关键环节&#xff0c;直接影响测试结果的准确性和可靠性。合理的缓存处理策略能够确保测试环境的一致性&#xff0c;避免因缓存数据导致的测试偏差。以下是接口测试中常见的缓存处理策略及其详细说明&#xff1a; 一、缓存处理的核…

龙虎榜——20250610

上证指数放量收阴线&#xff0c;个股多数下跌&#xff0c;盘中受消息影响大幅波动。 深证指数放量收阴线形成顶分型&#xff0c;指数短线有调整的需求&#xff0c;大概需要一两天。 2025年6月10日龙虎榜行业方向分析 1. 金融科技 代表标的&#xff1a;御银股份、雄帝科技 驱动…

观成科技:隐蔽隧道工具Ligolo-ng加密流量分析

1.工具介绍 Ligolo-ng是一款由go编写的高效隧道工具&#xff0c;该工具基于TUN接口实现其功能&#xff0c;利用反向TCP/TLS连接建立一条隐蔽的通信信道&#xff0c;支持使用Let’s Encrypt自动生成证书。Ligolo-ng的通信隐蔽性体现在其支持多种连接方式&#xff0c;适应复杂网…

铭豹扩展坞 USB转网口 突然无法识别解决方法

当 USB 转网口扩展坞在一台笔记本上无法识别,但在其他电脑上正常工作时,问题通常出在笔记本自身或其与扩展坞的兼容性上。以下是系统化的定位思路和排查步骤,帮助你快速找到故障原因: 背景: 一个M-pard(铭豹)扩展坞的网卡突然无法识别了,扩展出来的三个USB接口正常。…

未来机器人的大脑:如何用神经网络模拟器实现更智能的决策?

编辑&#xff1a;陈萍萍的公主一点人工一点智能 未来机器人的大脑&#xff1a;如何用神经网络模拟器实现更智能的决策&#xff1f;RWM通过双自回归机制有效解决了复合误差、部分可观测性和随机动力学等关键挑战&#xff0c;在不依赖领域特定归纳偏见的条件下实现了卓越的预测准…

Linux应用开发之网络套接字编程(实例篇)

服务端与客户端单连接 服务端代码 #include <sys/socket.h> #include <sys/types.h> #include <netinet/in.h> #include <stdio.h> #include <stdlib.h> #include <string.h> #include <arpa/inet.h> #include <pthread.h> …

华为云AI开发平台ModelArts

华为云ModelArts&#xff1a;重塑AI开发流程的“智能引擎”与“创新加速器”&#xff01; 在人工智能浪潮席卷全球的2025年&#xff0c;企业拥抱AI的意愿空前高涨&#xff0c;但技术门槛高、流程复杂、资源投入巨大的现实&#xff0c;却让许多创新构想止步于实验室。数据科学家…

深度学习在微纳光子学中的应用

深度学习在微纳光子学中的主要应用方向 深度学习与微纳光子学的结合主要集中在以下几个方向&#xff1a; 逆向设计 通过神经网络快速预测微纳结构的光学响应&#xff0c;替代传统耗时的数值模拟方法。例如设计超表面、光子晶体等结构。 特征提取与优化 从复杂的光学数据中自…