新闻详情

新闻详情

首页 / 资讯中心 / 详情

C语言指针进阶:数组指针、函数指针与二级指针实战解析

发布时间:2026/10/2 4:27:57来源:尧图网络
C语言指针进阶:数组指针、函数指针与二级指针实战解析
上次聊指针的时候我们把最基础的那点东西讲完了——指针是一个变量、里面存的是地址、通过解引用可以访问它指向的内存。但很多人学到这一碰真正的代码还是发懵int *p和int (*p)[4]到底差在哪char *p[]和char (*p)[]怎么一个读成一个读不通p到底是加了几个字节为什么函数里改完指针外面还是没变这篇文章就是针对这些进阶问题的。我会从指针的本质继续往下挖把数组与指针的纠缠、二级指针、函数指针、const与指针的组合、结构体指针以及最常见的野指针和越界问题都过一遍。中间穿插大量可以直接编译运行验证的代码还会告诉你哪些地方是我自己当年踩过的坑希望帮你把指针从“背概念”变成“真懂”。老规矩手里有编译器的可以边看边敲只看不练的话下次碰到段错误照样一脸懵。1. 指针到底是什么脱离“地址”两字的误区1.1 地址是骨架类型才是灵魂很多人觉得指针装的就是地址那我用int *和char *有什么区别反正都是 4 字节32 位平台或者 8 字节64 位平台的地址。这么说对了一半。地址确实是同样的门牌号但编译器真正关心的是门牌号指向的那个房间长什么样。int *p是“我拿着一个门牌号打开这扇门我要按 4 字节来读取和解释里面的数据”char *p则按 1 字节来读取。类型标签跟着指针走它决定了三件事解引用时读多少字节、按什么方式解释那串二进制、以及指针做加减时一次跨多大的步长。比如同样一个地址0x7ffe1234用int *去解引用编译器会从那块地址连续取 4 个字节用char *去解引用只取 1 个字节。你可以写一个小程序验证#include stdio.h int main(void) { int x 0x12345678; int *ip x; char *cp (char *)x; printf(ip %p, *ip 0x%x\n, (void *)ip, *ip); printf(cp %p, *cp 0x%x\n, (void *)cp, (unsigned char)*cp); return 0; }我当年第一次看到*cp输出0x78时还挺意外的后来才知道这是小端字节序——低字节存在低地址。这事看着小但做通信协议解析、文件格式解析时非常关键。1.2 指针加减跨的是“步长”不是“字节数”这是特别容易翻车的地方。很多人写p 1潜意识里觉得就是地址值加 1结果打印一看地址差了 4 个字节。因为p 1的真实含义是“指向下一个同类型的元素”编译器得按类型大小去算偏移。#include stdio.h int main(void) { int a[3] {10, 20, 30}; int *ip a; char *cp (char *)a; printf(ip %p\n, (void *)ip); printf(ip1 %p\n, (void *)(ip 1)); printf(cp %p\n, (void *)cp); printf(cp1 %p\n, (void *)(cp 1)); return 0; }对int *ipip 1地址偏移sizeof(int)对char *cpcp 1只偏移 1 字节。如果不懂步长你在二维数组和自定义结构体数组里遍历时很容易算错偏移甚至访问到元素中间去。顺带说一句标准 C 里对void *做1是非法的。因为void没有类型大小编译器不知道步长是多少。想拿它当“泛型指针”来回挪的话思路是有但得先转换成具体类型的指针再挪。1.3 数组为什么可以用指针来遍历数组和指针不是同一个东西但数组名会在表达式中“退化”成指针。int a[5]里a在大多数场合代表“指向a[0]的指针”。于是a[2]和*(a 2)在编译器眼里是同一回事。用指针遍历数组的时候怎么判断结束常见做法是指针指向数组开头然后一直后移直到越过数组末尾int arr[5] {1, 2, 3, 4, 5}; int *p arr; int *end arr 5; // 指向数组最后一个元素的下一个位置 while (p end) { printf(%d , *p); p; }这里arr 5是个“过界但合法”的位置只用于比较不许解引用。很多库函数也是这么干的比如 C 标准库里的范围约定就是“左闭右开”。2. 数组与指针的经典纠缠2.1a与a的区别同一个数字不同的步长感受一下这个int a[5] {1, 2, 3, 4, 5}; printf(%p\n, (void *)a); printf(%p\n, (void *)a);打印出来一样两个地址值相同。但下面再看看printf(%p\n, (void *)(a 1)); // 偏移 4 字节 printf(%p\n, (void *)(a 1)); // 偏移 20 字节a退化为int *所以a 1跳过一个 int。a类型是int (*)[5]一个指向整个数组的指针所以a 1直接跳过了整个数组的 5 个 int。当年我面试实习岗位面试官就拿着代码问我这个我答完地址相同又答了步长不同他才点头。这个知识点是 C 语言基础题里的高频考点对应在很多学校的编程题、PTA 题目里大家务必亲手打印验证。2.2 指针数组还是数组指针先和谁结合说了算这组概念绕晕了无数人。给出两个声明char *strs[3]; // 指针数组一个数组元素是 char* char (*pstr)[3]; // 数组指针一个指针指向“含有 3 个 char 的数组”记住一个读法技巧从变量名出发看它先和谁结合。[]的优先级高于*所以char *strs[3]里strs先和[3]结合说明首先它是一个数组数组里每个元素类型是char *也就是每个元素能存一个字符串的首地址。这正好对应上面热搜词里“指针数组存放字符串”。再看char (*pstr)[3]括号强行使pstr先和*结合说明它首先是一个指针指针指向的对象是char[3]也就是一个能装 3 个字符的数组。这两者天差地别。需要在实际项目里怎么选如果要存一组字符串结尾可以直接用指针数组char *strs[] {hello, world, c language}; for (int i 0; i 3; i) { printf(%s\n, strs[i]); }这里每个字符串常量存放在只读区strs[i]保存的是它们各自的地址数组本身不复制字符串内容。想修改字符串内容的话需要改成二维字符数组这个后面会说。2.3 二维数组的指针访问行指针是怎么回事二维数组int matrix[3][4]在内存里依然是一段连续空间共 12 个 int。你可以用“扁平指针”从头扫到尾int matrix[3][4] { {1, 2, 3, 4}, {5, 6, 7, 8}, {9, 10, 11, 12} }; int *p matrix[0][0]; for (int i 0; i 12; i) { printf(%d , p[i]); }也可以用“行指针”int (*row)[4]指向某一行然后按二维下标访问int (*row)[4] matrix; // row 指向第一行类型为 int(*)[4] printf(%d\n, row[1][2]); // 第 1 行第 2 列 7我自己在写图像处理类的程序时常用行指针因为很多时候需要按行做卷积、滤波、行交换这时候行指针语义清晰不容易算错偏移。而处理整块缓冲区时扁平指针更高效。两种方式要都能写。顺带提一句二维数组作为函数参数时会退化成“指向数组的指针”比如void foo(int arr[3][4])等价于void foo(int (*arr)[4])。第二维必须给出因为编译器要通过它计算每行的步长。这也就是为什么热搜词里“c语言多维数组指针”反复出现。3. 指针运算与字符串处理实战3.1 字符串逆序指针版本怎么做“字符串逆序”在 C 语言练习题里非常常见PTA 上也有对应题目。指针写法很标准核心是双指针向中间夹逼#include stdio.h #include string.h void reverse(char *s) { char *left s; char *right s strlen(s) - 1; while (left right) { char tmp *left; *left *right; *right tmp; left; right--; } } int main(void) { char buf[] hello c language; reverse(buf); printf(%s\n, buf); return 0; }关键细节是终止条件。left right已经足够好不需要因为当两指针相遇时再交换会恢复原样等于白做。strlen(s) - 1要小心空字符串时strlen为 0right会变成s - 1那就不对了所以实际项目里应先判断空串。还有一个更大的坑如果你写的是char *s hello;而不是char s[] hello;那s指向的是字符串常量存在只读区你去修改*s会直接崩溃或者未定义行为。所以做这类操作一定用字符数组。3.2 指针作为循环条件的常见隐患用指针遍历字符串的典型写法是while (*p) { ... p; }因为字符串末尾有\0读取它是 0循环自然停止。这个写法干净高效但要确保两点指针必须真的指向一个以\0结尾的内存区域且不能越界访问到别的内存。我帮别人改过一段代码他用while (*p ! \0)遍历一个自己拼装的缓冲区结果缓冲区末尾没置\0程序一直往后读读到随机内存里碰上一个 0 才停中间全是垃圾字符。所以动态分配缓冲区时记得在末尾手动补\0或者用calloc直接让内存初始化成全 0。3.3 双指针法的套路理解热搜词里“双指针法”也出现了这在算法题里很常见本质上就是两个指针在同一个数组或链表中移动一个快一个慢或者一左一右夹逼。刚才的字符串逆序就是左右双指针。冒泡排序写指针版时也可以用双指针界定未排序区间。这里不提前展开太多算法内容但要知道指针运算配合循环、条件比较是解决很多问题的底层逻辑。C 语言里“指针操作”“数组下标操作”可以互相转换熟读上面这些例子后再看while (left right)这类的算法代码就不会再觉得抽象了。4. 二级指针与多级指针4.1 一级指针为什么不够先看一个经典场景。写一个函数想让它把外部指针p指向新分配的内存#include stdio.h #include stdlib.h void alloc_int(int *p) { p (int *)malloc(sizeof(int)); *p 42; } int main(void) { int *p NULL; alloc_int(p); printf(%d\n, *p); // 崩溃吧 return 0; }上面这段代码必崩。原因是参数传递是值传递函数里的p是外部p的拷贝。你改变拷贝外部指针还是NULL。想修改指针变量本身就要把“指针变量的地址”传进去那就需要二级指针int **ppvoid alloc_int(int **pp) { *pp (int *)malloc(sizeof(int)); if (*pp ! NULL) { **pp 42; } } int main(void) { int *p NULL; alloc_int(p); if (p ! NULL) { printf(%d\n, *p); free(p); } return 0; }这里pp存放的是p的地址*pp拿到的是p本身**pp拿到的是p指向的 int。很多人刚学时绕不过来我用过的一个类比是一级指针是“遥控器”通过它你可以操控电视二级指针是“装遥控器的盒子”通过它你能换一个遥控器来操控电视。4.2 二级指针的三个典型应用除了函数内修改外部指针常见的场景还有第一在函数里给外部指针重新分配内存比如栈结构、树结构里的插入操作。第二指针数组作为参数传入函数时char *strs[]会退化成char **strs。第三链表中删除头结点时如果直接操作头指针本身也要用到二级指针。看一个指针数组传参的例子#include stdio.h void print_names(char **strs, int n) { for (int i 0; i n; i) { printf(%s\n, strs[i]); } } int main(void) { char *names[] {alice, bob, carol}; print_names(names, 3); return 0; }形参char **strs和实参char *names[]在函数调用时是一致的因为数组名退化成指针。strs[i]本质是*(strs i)取到的是第 i 个字符串的首地址。4.3 多级指针别用太多二级指针常见三级四级理论上也可以有比如int ***ppp。但说实话三级以上代码可读性就很差了。我自己见过有人为了炫技写出三级指针后来维护的同事直接崩溃。能用结构体封装解决的就不要层层套娃。指针的目的是表达意图不是制造障碍。5. 函数指针与回调机制5.1 函数名本身就是一个地址每个函数编译后也占据一段内存函数名可以理解为这段内存的入口地址。所以可以定义一个指针保存这个地址然后通过指针调用函数。#include stdio.h int add(int a, int b) { return a b; } int main(void) { int (*fp)(int, int) add; printf(%d\n, fp(3, 4)); printf(%d\n, (*fp)(3, 4)); // 和上面等价 return 0; }int (*fp)(int, int)的读法fp先和*结合说明是一个指针后面跟着(int, int)说明它指向一个接收两个 int 参数、返回 int 的函数。初学的时候很容易把int *fp(int, int)和它搞混。后者是“一个函数参数是两个 int返回值是int *”。优先级规则在这是关键记不清就套用上面的“看先和谁结合”。5.2 typedef 精简函数指针声明函数指针的真实威力在于把函数当成数据来传递。为了写起来好看一般用typedef给函数指针类型起个别名typedef int (*MathOp)(int, int);以后就可以直接写MathOp op add; printf(%d\n, op(5, 6));这种写法在驱动开发、菜单程序、状态机、插件系统里非常常见。比如做一个四则运算计算器可以把四个函数放进一个函数指针数组里用一个索引直接调用比一串switch case清爽很多。这也是“函数指针与指针函数”这个热搜词总被反复提问的原因——它俩完全不是一回事。指针函数是“返回指针的函数”函数指针是“指向函数的指针”。5.3 回调机制用 qsort 看看标准库怎么用C 标准库的qsort是一个最经典的函数指针应用。它需要你来告诉它“两个元素谁大谁小”于是你得写一个比较函数然后把它的地址传进去#include stdio.h #include stdlib.h int cmp_int(const void *a, const void *b) { int x *(const int *)a; int y *(const int *)b; if (x y) return -1; if (x y) return 1; return 0; } int main(void) { int arr[] {4, 2, 9, 1, 7}; int n sizeof(arr) / sizeof(arr[0]); qsort(arr, n, sizeof(int), cmp_int); for (int i 0; i n; i) { printf(%d , arr[i]); } printf(\n); return 0; }这里有几个非常值得注意的细节。第一比较函数的参数是const void *因为qsort设计成对任意类型数组都能用所以得用void *接收“未知类型元素的地址”。第二在比较函数内部做强制转换后先解引用再比较把 void 指针转回具体类型指针。第三返回值的正负零语义必须写对写反了排序结果就是反的。排序结构体数组时同理只是强制转换的目标类型改成const struct student *然后比较结构体里的某个字段。这是很多课程设计和做实际工具时经常用的手段。6. const 与指针的组合三种写法的坑6.1 三种组合分别锁住什么这部分也是面试最基础的送分题但很多人分不清。三种写法const int *p; // p 可以指向别处但不能通过 p 修改所指数据 int *const p; // p 不能指向别处但可以通过 p 修改所指数据 const int *const p; // 两个都不能改理解的关键是const修饰的是谁。一个朴素的读法是先看const和*的相对位置const在*左边修饰的是*p也就是“被指向的数据”const在*右边修饰的是p本身。写成int const *p和const int *p是等价的都是修饰被指向的数据。写代码验证一下int a 10; int b 20; const int *p a; p b; // 合法p 可以换指向 // *p 30; // 非法不能通过 p 修改数据 int *const q a; // q b; // 非法q 不能换指向 *q 30; // 合法可以通过 q 修改数据6.2 实际开发里的选择习惯我在写函数参数时如果这个函数只读字符串、不修改内容我会写成const char *str。这样有三个好处文档效果告诉调用者我不会改你的数据、编译检查不小心写改操作编译器能拦住、兼容性字符串常量也能传进去。如果函数里要直接移动指针去遍历但不修改内容也可以写成const char *s然后自己做s。这时你会发现const修饰的是“s 指向的内容”而s本身不是 const所以s合法。能分清这个细节前面那段就真学会了。6.3 强制转换能不能抛弃 const有时候为了调用某个库函数它没有 const但你的参数是 const编译会报警告。你可以用(char *)强制转换去掉 const。能做但不到万不得已不要做。去掉 const 等于自己签字承诺“我要改这块数据”如果实际上这块区域在只读段用了就崩溃。代码里能少一个强制转换就少一个除非你非常清楚底层是什么。7. 结构体指针与链表指针在数据结构的落点7.1 结构体指针的访问方式结构体在内存里是一块连续的存储区结构体指针指向它的首地址。访问成员一般用箭头操作符-#include stdio.h #include stdlib.h #include string.h typedef struct Student { int id; char name[32]; double score; } Student; int main(void) { Student *s (Student *)malloc(sizeof(Student)); if (s NULL) { return 1; } s-id 1001; strcpy(s-name, zhangsan); s-score 92.5; printf(%d %s %.2f\n, s-id, s-name, s-score); free(s); return 0; }这里最容易犯的错是拿到结构体指针后直接s-name xxx。s-name是一个数组名不是指向字符的指针变量不能直接赋值得用strcpy。很多从 Java 转 C 的朋友经常在这一步怀疑人生。7.2 链表头插法修改链的顺序很重要链表是大学 C 语言课程设计的常客也是“结构体指针”最直接的用武之地。看一个最简单的头插法typedef struct Node { int data; struct Node *next; } Node; Node *insert_head(Node *head, int val) { Node *new_node (Node *)malloc(sizeof(Node)); if (new_node NULL) { return head; } new_node-data val; new_node-next head; head new_node; return head; }顺序问题很关键一定要先把新节点的next指向原head再把头指针更新成new_node。如果反过来先改head new_node原链表就跟丢了那部分内存会泄漏。删除节点时如果删除的是头结点需要特殊处理这也是很多人用二级指针的原因把Node **pp传进函数才能直接修改实参头指针。比如删除第一个值为val的节点void delete_node(Node **pp, int val) { while (*pp ! NULL) { if ((*pp)-data val) { Node *tmp *pp; *pp (*pp)-next; free(tmp); return; } pp (*pp)-next; } }看着晕但它其实是在用pp保存“上一个节点的 next 指针的地址”。这样无论删除头结点还是中间节点操作方式完全统一不需要特判。我建议手动画一下链表示意图把*pp、(*pp)-next的指向画清楚比背代码可靠。7.3 结构体指针与内存管理malloc之后一定要判断是否返回NULL。用完free之后最好把指针置为NULL。因为free后指针本身变成了“悬空指针”虽然地址还在但指向的内存已经归还系统再解引用就是未定义行为。这种问题在大型程序里极易排查到崩溃。用valgrind工具可以查内存泄漏和非法访问比如在 ubuntu 的终端运行valgrind --leak-checkfull ./test。如果你在虚拟机里配了 C 环境建议装一个这是检查指针问题的利器。8. 完整实战用指针遍历统计字符串里的单词数8.1 需求场景写个小函数统计一句话里包含多少个单词单词之间用空格分隔。要求使用指针遍历字符串不能用数组下标。这个题看起来简单但把指针循环、状态判断、边界处理全串起来了。8.2 完整代码与解析#include stdio.h int count_words(const char *s) { int count 0; int in_word 0; while (*s ! \0) { if (*s || *s \t || *s \n) { in_word 0; } else if (!in_word) { in_word 1; count; } s; } return count; } int main(void) { char line[128] hello world, this is c language; printf(words: %d\n, count_words(line)); return 0; }核心逻辑是维护一个状态变量in_word碰到空格就标记“不在单词里”碰到非空格且此前不在单词里就说明一个新单词开始了计数加一。这样连续多个空格也不会重复计数开头和结尾的空格也不会干扰。因为s声明为const char *函数内部只能读取不能修改但s是可以的因为锁住的是“内容”而不是指针本身。8.3 这个例子里容易踩的坑第一用gets读字符串不安全遇到超长输入会溢出缓冲区强烈建议用fgetsfgets(line, sizeof(line), stdin);fgets会把换行符也读进来所以如果你不想把换行当作单词分隔符需要在统计逻辑里把\n也当成空白处理上面的代码已经考虑了。第二字符串开头如果直接是空格in_word初始值必须为 0否则会把开头空格后第一个单词漏掉。第三空字符串返回 0而不是 1。这个示例还可以扩展成“统计字符串里有多少个大写字母”“把单词逐个翻转”等核心都是指针遍历和状态判断建议自己动手改改。9. 指针常见错误的排查与避坑心得9.1 野指针、悬空指针、越界访问三件事这三类是 C 程序崩溃的主要来源。野指针是没有初始化的指针里面存的是一个随机地址悬空指针是free或返回局部变量地址后指针还在但内存已失效越界访问是拿着指针越过了合法内存区域。很多人的程序在 Release 版偶尔崩、Debug 版不崩极常见的原因就是越界或者悬空指针刚好访问到了还没被系统回收的地址。等一阵子内存被别的新数据覆盖旧指针再去读就出现各种匪夷所思的结果。9.2 排查建议第一先编译期开警告。GCC 编译时建议加上-Wall -Wextra很多明显的指针类型不匹配、变量未初始化问题会在编译期暴露。第二使用地址消毒器。用-fsanitizeaddress编译运行时报出非法访问的精确位置。这个工具对学生课程设计或者个人练手非常有效。第三规范初始化。指针声明就置为NULL用完释放后也置为NULL每次使用前判断是否为NULL能挡掉一大批问题。9.3 常见问题速查表错误现象可能原因快速排查方法程序运行就崩溃空指针或野指针解引用打印指针值确认是否为 NULL 或非预期地址逻辑时而对时而不对越界写入破坏了邻近数据用 AddressSanitizer 或缩小数据规模复现free后崩溃重复释放悬空指针检查是否已置 NULL使用 Valgrind 查看排序或遍历结果错类型步长算错指针偏移错误打印每次移动后的地址值修改字符串崩溃给字符串常量通过指针写了值检查是不是char *指向了字面量我自己的习惯是出了指针相关的诡异问题先printf(%p\n, (void *)p)把每个关键阶段的地址打出来和预期偏移做比对。很多时候地址差 8 个字节或者差 4 个字节就能一下子看出来是步长问题还是指错了位置。这一招在 gdb 单步调试时配合p命令效率特别高。最后再分享一个我的体会学指针没有捷径但有一个很实用的路径。找十道经典的字符串题目比如字符串逆序、单词统计、括号匹配、子串查找之类全部用指针写一遍再用下标写一遍比较两者差别。这个过程比单纯看十遍课本有效得多。等你写顺手了回头再看“数组指针”“函数指针”“二级指针”这些概念你会发现它们只是同一个底层机制在不同场景下的自然表达一点也不神秘。
网站建设高端定制企业官网
RELATED

相关资讯

更多精彩内容,欢迎继续阅读

较早相关资讯

最新相关资讯

四个指标公式原码图无未来下周大盘密钥分析 2026/10/2 7:07:28

四个指标公式原码图无未来下周大盘密钥分析

VAR3:(2*CLOSEHIGHLOW)/4; VAR4:LLV(LOW,34); VAR5:HHV(HIGH,34); QYYJ:EMA((VAR3-VAR4)/(VAR5-VAR4)*100,13); RQQ:EMA(0.667*REF(QYYJ,1)0.333*QYYJ,2); DRAWTEXT(CROSS(QYYJ,RQQ) AND QYYJ<10,L-0.2,低吸),COLORCYAN;AR26R:(CLOSE-LLV(LOW,27))/(HHV(HIGH,27)-LLV(LOW,27…

阅读更多 →
亲测12款论文降AI率工具,效果最稳的竟然是它! 2026/10/2 7:07:28

亲测12款论文降AI率工具,效果最稳的竟然是它!

最近真的有太多人问我&#xff1a;"论文 AI 率太高怎么办&#xff1f;学校现在查 AI 检测比查重还严&#xff0c;连人工改的都过不了&#xff01;" 我特别理解这种焦虑&#xff0c;因为我自己前段时间也踩过坑。各种号称降低 AI 率的工具试了一圈&#xff0c;有的乱扣…

阅读更多 →
一文读懂嵌入式知识系列:从C语言到可执行文件 2026/10/2 7:07:28

一文读懂嵌入式知识系列:从C语言到可执行文件

前言很多嵌入式开发者写了多年C语言&#xff0c;熟练实现串口、定时器、中断等功能&#xff0c;却始终搞不懂一个核心问题&#xff1a;我们写的C代码&#xff0c;到底是怎么变成单片机、ARM板子能识别、能运行的可执行程序的&#xff1f;平时IDE一键编译、下载程序的操作&#…

阅读更多 →
数据合规的同意记录怎么留存? 2026/10/2 7:07:28

数据合规的同意记录怎么留存?

如果你正在过 App 合规检查、整理同意日志&#xff0c;这篇可以直接当清单&#xff0c;对照自己的弹窗版本和日志字段查漏补缺。结论先说&#xff1a;同意记录不是一张弹窗截图&#xff0c;而是一条"谁、在什么时间、看到哪个版本的文案、点了什么、后来有没有撤回"的…

阅读更多 →
6款论文AI智能降重工具亲测:AI率直降安全线,学生党必入平价款 2026/10/2 7:07:28

6款论文AI智能降重工具亲测:AI率直降安全线,学生党必入平价款

2026年毕业季临近&#xff0c;知网、维普两大国内核心学术平台已完成AIGC检测算法的全面迭代升级&#xff1a;知网将AI检测模型更新至3.0版本&#xff0c;实现句子级精准识别&#xff0c;对AI生成内容的识别能力提升15-18个百分点&#xff1b;维普则重构检测逻辑&#xff0c;新…

阅读更多 →
一文读懂OSI与TCP/IP:TCP/UDP原理、可靠传输与iperf3验证实验 2026/10/2 7:07:22

一文读懂OSI与TCP/IP:TCP/UDP原理、可靠传输与iperf3验证实验

写这篇东西的起因很直接&#xff1a;不管是准备计算机网络考试、复习 408&#xff0c;还是被面试官追问“打开一个网页背后发生了什么”&#xff0c;你迟早都得和 OSI 七层模型、TCP/IP 协议栈、TCP 三次握手、UDP 这些词正面相遇。我在这个方向待了很多年&#xff0c;也给不少…

阅读更多 →

今日资讯

本周资讯

本月资讯

看完文章仍有疑问?

联系尧图顾问,获取一对一建站咨询

立即免费咨询 📞 400-888-8888
📞 ✉