当前位置: 首页 > news >正文

11_指针入门_地址指针变量解引用与指针运算

指针入门:地址、指针变量、解引用与指针运算

一、本篇文章要解决什么问题

如果你问学过 C 语言的人"什么最难",十个人里有八个会说"指针"。

不是指针本身有多难,而是它在教法上出了很多问题:很多教材一上来就扔给你int *p = &a; *p = 10;这种代码,然后让你死记硬背"星号是解引用,取地址符是取地址"。你背是背下来了,但回到座位上还是不知道指针到底在干什么。

这篇文章要做的不是让你背公式,而是帮你从内存的角度真正理解指针。具体要回答这些问题:

  1. 为什么要发明指针?没它行不行?
  2. 内存地址到底是什么,长什么样?
  3. 指针变量和普通变量有什么区别?
  4. &*到底在做什么?
  5. 什么是空指针?什么是野指针?为什么野指针比编译错误可怕得多?
  6. 指针加减 1 为什么有时候加 1 个字节,有时候加 4 个字节?

这篇文章是四篇指针系列的第一篇,是所有指针知识的"地基"。看完这篇,后面讲数组和指针、函数和指针的时候,你才不会觉得像在看天书。


二、先用一个简单例子理解

2.1 图书馆找书的故事

假设你在一座大图书馆里找一本书。有三种办法知道书在哪:

办法一:你手里直接拿着一本实体书。任何时候翻开就能读,但你只能同时拿一本书,换书就得跑回书架。

这个"直接拿着书"就相当于 C 语言里的普通变量

办法二:你手里不拿书,而是拿一张纸条,上面写着"这本书在 3 楼 A 区第 7 排第 12 格"。你顺着纸条上的信息去找,就能拿到书。而且一张纸条可以随时改成指向另一本书。

这个"纸条上记着书的位置"就是C 语言的指针

办法三:你手里拿一张纸条,上面写着"看第二张纸条",第二张纸条上才写着书的位置。这就是二级指针(第 12 篇会讲)。

2.2 为什么需要"纸条"(指针)

现在问你:如果你要写一个函数,这个函数要能修改外面某个变量的值,怎么办?

上一篇讲函数的时候说过,C 语言默认是"值传递"——你把变量传给函数,函数拿到的是一个副本,改了副本不影响原变量。

voidaddTen(intx){x=x+10;// 改的是副本,外面的变量不变}

那如果我就是想让函数能修改外面的变量呢?比如写一个swap函数交换两个变量的值?

这时候就需要指针了。你不把"值"给函数,而是把"变量的地址"给函数。函数顺着地址找到变量本身,就能修改它。就像你告诉朋友"那本书在书架第三格",朋友就可以自己去拿书或换书——不需要你亲自跑一趟。

这就是指针存在的核心原因:让一段代码能够访问和修改另一段代码里的数据,而不需要把整个数据复制一份。


三、核心知识点讲解

3.1 什么是内存地址

要理解指针,先要理解内存。

把计算机内存想象成一条超级长的街道,街道两边排列着一栋栋房子。每栋房子有两个属性:

  • 门牌号(地址):比如 0x1000、0x1001、0x1002……这是唯一标识这个房子的编号
  • 里面的住户(数据):比如整数 10、字符 ‘A’,这是真正存的东西
内存模型(简化版): 地址: 0x1000 0x1001 0x1002 0x1003 0x1004 0x1005 0x1006 0x1007 ┌────────┬────────┬────────┬────────┬────────┬────────┬────────┬────────┐ 内容: │ │ │ │ │ │ │ │ │ └────────┴────────┴────────┴────────┴────────┴────────┴────────┴────────┘ <-- 每个格子 1 个字节 --> 当你写: int a = 10; 编译器在内存里找一个空闲区域,占 4 个连续字节(因为 int 是 4 字节), a 这个变量名就是这 4 个字节的"别名"。 地址: 0x1000 0x1004 ┌──────────────────────────┐ 内容: │ 10 00 00 00 │ <-- a 的值 10(二进制形式存储) └──────────────────────────┘ ↑ a 的地址是 0x1000(取这 4 个字节的起始地址)

关键理解:在 C 语言里,每个变量在定义的时候,编译器就在内存里给它分配了一块空间。这块空间的起始字节的编号,就是这个变量的地址。你可以用&运算符拿到这个地址。

3.2 & 运算符:取地址

&是"取地址"运算符。把它放在一个变量前面,就得到这个变量在内存中的地址。

inta=10;printf("a 的值是:%d\n",a);// 输出 10printf("a 的地址是:%p\n",(void*)&a);// 输出类似 0000008A3C6FF794

%p是专门用来打印地址的格式占位符。你每次运行程序,输出的地址可能不一样——这是操作系统分配的,不同机器、不同时刻运行结果都不同。所以不要指望地址是一个固定的数字,你只需要理解:它是一个能唯一找到某个变量的"门牌号"。

图11-1 变量、地址与指针的关系(重点):这是全篇最核心的图,帮读者一次看清楚普通变量、指针变量、取地址、解引用四个概念的关系。

3.3 指针变量:一个专门存地址的变量

知道了地址是什么,指针变量就好理解了:

指针变量就是一个变量,但这个变量不存"常规数据",而是存"另一个变量的地址"。

inta=10;// 一个普通整数变量,存的是 10int*p=&a;// 一个指针变量,存的是 a 的地址

怎么读int *p

很多初学者卡在"指针的语法"上。推荐你这样理解:

  • int *p的意思是:*p是一个int类型的数据
  • 倒推回去:p是一个指针,它指向的那个数据是int类型的

或者更简单的读法:“p 是一个指向 int 的指针”

3.4 内存示意图:变量、地址、指针的关系

下面这张图是理解指针最关键的一张图。建议你花 3 分钟认真看:

假设 a 的地址是 0x1000,p 的地址是 0x2000 内存布局: 地址 0x1000 (变量 a 的起始地址) ┌─────────────────────┐ │ 10 │ ← a 的值(int 占 4 字节) └─────────────────────┘ ↑ │ p 保存了这个地址 │ 地址 0x2000 (变量 p 的起始地址) ┌─────────────────────┐ │ 0x1000 │ ← p 的值(存的是地址,通常占 4 或 8 字节) └─────────────────────┘ 关系: a 的值是 10 &a 的值是 0x1000 p 的值是 0x1000(也就是 &a) *p 的值是 10 (顺着 p 里存的地址找到的那个数据) 口诀: & 是"问你在哪" —— &a 得到 a 的地址 * 是"去那个地址看看里面有什么" —— *p 得到 p 指向的那个地址里的内容

3.5 * 运算符:解引用(间接访问)

*放在指针变量前面,意思是"顺着这个指针里存的地址,去找到那个地址里存的数据"。这个操作叫解引用,也叫间接访问

inta=10;int*p=&a;printf("*p = %d\n",*p);// 输出 10,因为 *p 就是 a*p=20;// 通过 p 间接修改 a 的值printf("a = %d\n",a);// 输出 20,a 真的被改了

运行结果:

*p = 10 a = 20

重要区别——定义时的 * 和使用时的 * 不是一回事:

int*p=&a;// 这里的 * 表示"p 是指针类型",不是解引用*p=20;// 这里的 * 是解引用操作,顺着 p 指向的地址去修改数据

同一个符号*,在定义语句中是"声明指针类型",在执行语句中是"解引用"。初学者经常混淆这两个含义,多写几次就习惯了。

图11-2 指针修改外部变量的流程:帮读者理解指针在函数参数传递中的核心价值,为第 13 篇做铺垫。

3.6 指针的初始化

指针在定义时必须初始化,或者至少给它一个明确的初始值。这是 C 语言里最严格的安全纪律。

正确做法——定义时初始化:

inta=10;int*p=&a;// 定义的同时初始化为 &a// 或者先定义,再赋值int*q;q=&a;// 正确:q 现在指向 a

危险做法——定义指针但不初始化:

int*p;// p 里面是一个随机值!*p=10;// 把 10 写到随机地址里——程序可能崩溃,或者更糟:静默破坏数据

int *p;定义了一个指针变量,但没有给它赋值。这时候 p 里面存的是什么?是一个随机的、不确定的地址值。这个值可能是 0x00000001,也可能是 0x8A3C6FF7——取决于这块内存上一次被用过之后残留了什么数据。然后你*p = 10;试图把 10 写到这个随机地址里。这相当于你随机拨了一个电话号码,然后对那个人说"你家沙发上现在放了一本书"——轻则没人理你(程序崩溃),重则真有人把书放上去了(破坏了其他数据)。

图11-3 指针运算步长示意图(重点):直观解释"为什么指针 +1 不是加 1 个字节",这是指针运算最容易困惑的地方。

3.7 空指针——一个安全的"空纸条"

为了让"未指向任何有效数据的指针"能被识别,C 语言规定了一个特殊值:NULL

int*p=NULL;// p 明确地"什么都不指"if(p!=NULL)// 使用前检查{*p=10;// 安全:确认 p 是有效的才访问}

NULL 的本质是一个等于 0 的地址。从 C 语言标准的角度,解引用 NULL 属于未定义行为——在实际的现代操作系统(Windows、Linux、macOS)上,地址 0 附近的内存受保护、不可读写,因此解引用 NULL 通常会导致程序立即崩溃。虽然"崩溃"听起来可怕,但这其实是好事:问题能被立刻发现和定位,比静默出错容易排查得多。

图11-4 空指针、野指针、悬空指针对比图:让初学者一眼区分三种"危险指针",知道什么情况用什么名字。

3.8 野指针——未初始化的"危险指针"

野指针是指从未初始化过的指针变量。它不等于 NULL,里面存的是一个随机的、不确定的地址值。因为if (p != NULL)检查不出来,使用它会导致未定义行为——程序可能崩溃,也可能悄悄破坏其他数据。

错误示例(不要复制运行,仅用于理解概念):

int*p;// 野指针!p 未初始化,里面是随机值*p=10;// 危险!把 10 写到随机地址——程序可能崩溃

3.9 悬空指针——指向"已作废"的地址

悬空指针是曾经指向一个有效对象,但该对象的生命周期结束后,指针仍然保留着原来的地址。它不等于 NULL,指向的地址曾经合法但现在已无效,访问它同样是未定义行为——而且比野指针更隐蔽,因为代码可能在测试时正常运行,换一个环境或时机就崩溃。

错误示例(不要复制运行,仅用于理解概念):

#include<stdio.h>int*getPointer(void){intx=10;return&x;// 危险!x 是局部变量,函数返回后 x 的内存就失效了}intmain(void){int*p=getPointer();// p 现在是一个悬空指针——指向已释放的栈内存// printf("%d\n", *p); // 未定义行为!可能正常,也可能崩溃return0;}

正确做法:不要让函数返回局部变量的地址。如果确实需要让函数"产出"一个指针,要么返回动态分配的内存(第 19 篇讲),要么让调用者传入地址让函数去填充。

3.10 空指针、野指针、悬空指针三者区别(重点!)

很多教程把这三个概念混在一起讲,初学者越看越迷糊。分开说:

类型定义解引用后果
空指针明确赋值为 NULL 的指针NULL(即 0)程序立即崩溃(好:能被发现)
野指针从未初始化过的指针随机值未定义行为——可能崩溃,可能悄悄破坏数据(差:难以排查)
悬空指针指向内存已经被释放的指针原来合法但现在无效的地址未定义行为——代码可能正常运行几个月后才出问题(最差)
int*p1=NULL;// 空指针——安全的int*p2;// 野指针——未初始化,p2 里是随机值// 悬空指针示例:int*p3;{inttemp=42;p3=&temp;// p3 指向 temp}// temp 被销毁,p3 变成悬空指针

3.11 指针运算:为什么指针 +1 不是加 1 个字节

先看一段代码,它的结果会让很多初学者感到意外:

#include<stdio.h>intmain(void){intarr[3]={10,20,30};int*p=arr;printf("p = %p\n",(void*)p);printf("p + 1 = %p\n",(void*)(p+1));printf("p + 2 = %p\n",(void*)(p+2));return0;}

运行结果(具体地址每次运行不同,但差值固定):

p = 0000008A3C6FF790 p + 1 = 0000008A3C6FF794 p + 2 = 0000008A3C6FF798

观察到什么了?p + 1的地址比p多了4,不是 1。p + 2多了8

原因pint *类型,它知道自己指向的是int(占 4 字节)。所以p + 1的意思是"往后跳过一个int的距离",而不是"往后偏移 1 个字节"。这个跳过的距离就是sizeof(int),也就是 4 字节。

内存示意图(假设 int 占 4 字节): arr[0] = 10 arr[1] = 20 arr[2] = 30 ┌─────────────────┬─────────────────┬─────────────────┐ │ 10 │ 20 │ 30 │ └─────────────────┴─────────────────┴─────────────────┘ ↑ ↑ ↑ p p+1 p+2 地址差 4 地址差 4 如果 p 是 char *,p+1 就只偏移 1 字节(因为 sizeof(char) = 1) 如果 p 是 double *,p+1 会偏移 8 字节(因为 sizeof(double) = 8)

这就是为什么指针类型很重要:指针的类型告诉编译器,每次做加减运算时要跳多远。int *pchar *p存的都是地址(地址本身没有类型之分),但编译器根据指针的类型来决定运算时的步长。

同样的道理,*p解引用时,指针类型告诉编译器"从这个地址开始读几个字节"。int *p读 4 字节,double *p读 8 字节。


四、完整代码示例

下面这个程序把本节所有知识点串在一起,你可以完整复制运行:

#define_CRT_SECURE_NO_WARNINGS#include<stdio.h>intmain(void){// ===== 第一部分:基本指针操作 =====printf("========== 第一部分:基本指针操作 ==========\n");inta=100;int*p=&a;// p 指向 aprintf("a 的值:%d\n",a);printf("a 的地址:%p\n",(void*)&a);printf("p 保存的地址:%p\n",(void*)p);printf("*p 的值(解引用):%d\n",*p);// 通过指针修改变量的值*p=200;printf("\n执行 *p = 200 之后:\n");printf("a 的值变成了:%d\n",a);printf("*p 的值变成了:%d\n",*p);// ===== 第二部分:空指针检查 =====printf("\n========== 第二部分:空指针检查 ==========\n");int*q=NULL;printf("q 的值(NULL):%p\n",(void*)q);if(q!=NULL){printf("q 不为空,*q = %d\n",*q);}else{printf("q 是空指针,不能解引用,跳过访问。\n");}// ===== 第三部分:指针运算 =====printf("\n========== 第三部分:指针运算 ==========\n");intarr[]={10,20,30,40,50};int*pArr=arr;// 数组名就是首元素地址,不需要 &printf("通过指针遍历数组:\n");for(inti=0;i<5;i++){printf("*(pArr + %d) = %d (地址: %p)\n",i,*(pArr+i),(void*)(pArr+i));}printf("\n验证:sizeof(int) = %u\n",(unsignedint)sizeof(int));printf("所以 int 指针每 +1,地址增加 %u\n\n",(unsignedint)sizeof(int));// ===== 第四部分:不同指针类型的步长对比 =====printf("========== 第四部分:不同指针类型的步长 ==========\n");charc='X';doubled=3.14;char*pc=&c;double*pd=&d;printf("char 指针 pc = %p, pc+1 = %p (增加 %u 字节)\n",(void*)pc,(void*)(pc+1),(unsignedint)sizeof(char));printf("double 指针 pd = %p, pd+1 = %p (增加 %u 字节)\n",(void*)pd,(void*)(pd+1),(unsignedint)sizeof(double));return0;}

关于(void *)强制转换%p要求参数是void *类型。虽然大多数编译器不强制,但为了代码规范和消除警告,把各种指针都转成(void *)再传给%p是标准做法。


五、运行结果

========== 第一部分:基本指针操作 ========== a 的值:100 a 的地址:0000008A3C6FF794 p 保存的地址:0000008A3C6FF794 *p 的值(解引用):100 执行 *p = 200 之后: a 的值变成了:200 *p 的值变成了:200 ========== 第二部分:空指针检查 ========== q 的值(NULL):0000000000000000 q 是空指针,不能解引用,跳过访问。 ========== 第三部分:指针运算 ========== 通过指针遍历数组: *(pArr + 0) = 10 (地址: 0000008A3C6FF7A0) *(pArr + 1) = 20 (地址: 0000008A3C6FF7A4) *(pArr + 2) = 30 (地址: 0000008A3C6FF7A8) *(pArr + 3) = 40 (地址: 0000008A3C6FF7AC) *(pArr + 4) = 50 (地址: 0000008A3C6FF7B0) 验证:sizeof(int) = 4 所以 int 指针每 +1,地址增加 4 ========== 第四部分:不同指针类型的步长 ========== char 指针 pc = 0000008A3C6FF773, pc+1 = 0000008A3C6FF774 (增加 1 字节) double 指针 pd = 0000008A3C6FF788, pd+1 = 0000008A3C6FF790 (增加 8 字节)

六、代码逐行解析

第一部分:基本指针操作

inta=100;int*p=&a;
  • 第一行:在内存中分配 4 个字节,存入整数 100,这片内存的代号是a
  • 第二行:在内存中另分配一块空间(通常 4 或 8 字节,取决于系统是 32 位还是 64 位),把a的地址存进去,这块空间的代号是p
printf("a 的地址:%p\n",(void*)&a);printf("p 保存的地址:%p\n",(void*)p);

注意这两行输出的是同一个地址。这说明p = &a确实把a的地址存到了p里。

*p=200;printf("a 的值变成了:%d\n",a);

通过*p(解引用)修改了 p 指向的那个内存位置的内容。因为 p 指向的是 a,所以 a 的值也跟着变了。这就是指针的核心能力:间接访问和修改数据。

第二部分:空指针检查

int*q=NULL;if(q!=NULL){...}

在用指针之前检查它是否为 NULL,是一个好习惯。虽然这里我们知道 q 肯定是 NULL(因为刚赋的值),但在真实项目中,指针经过多次传递后,你无法确定它是否有效——先检查再用。

第三部分:指针运算——遍历数组

int*pArr=arr;// 不需要 &,因为数组名本身就是地址

arr的值就是数组首元素的地址,所以int *pArr = arr等价于int *pArr = &arr[0]

for(inti=0;i<5;i++){printf("*(pArr + %d) = %d\n",i,*(pArr+i));}
  • pArr + 0指向第一个元素,*(pArr + 0)得到 10
  • pArr + 1指向第二个元素(地址偏移了 4 字节!),*(pArr + 1)得到 20
  • 这种*(pArr + i)的写法等价于arr[i],实际上编译器就是按这种方式处理数组下标的

第四部分:不同指针类型步长对比

char*pc=&c;double*pd=&d;

我们看到pc + 1只增加了 1 字节(因为sizeof(char) = 1),而pd + 1增加了 8 字节(因为sizeof(double) = 8)。指针的类型决定了它运算时的步长,这是理解后面"指针与数组"的关键。


七、初学者常见错误

错误1:定义多个指针时忘了给每个加 *

// 错误写法int*p,q;// 你以为是两个指针,实际只有 p 是指针,q 是普通 int!// 正确写法int*p,*q;// 每个指针变量都要有自己的 *// 或者分开写,更清晰int*p;int*q;

这是 C 语言语法的一个坑。int *p, q;里,*只修饰pq是普通的int。推荐每个指针单独一行,清楚又安全。

错误2:解引用未初始化的指针

// 危险写法int*p;*p=100;// p 指向哪?不知道!程序可能崩溃// 安全写法inta;int*p=&a;*p=100;// 安全:p 明确指向 a

这是 C 语言初学者最容易犯的严重错误,而且编译器不一定报错。一定要记住:指针定义后立即让它指向一个有效地址,或者设为 NULL。

错误3:把 & 和 * 的含义搞反

inta=10;int*p=&a;// &a —— 取 a 的地址("a 住在哪")// *p —— 访问 p 指向的那个数据("去 p 记的地址看看里面有什么")// 错误理解:& 是"里面的内容",* 是"地址"// 正确理解:& 是"地址",* 是"这个地址里的内容"

口诀:& 看右边,得到地址;* 看右边,得到数据。

错误4:没有意识到局部变量的地址在函数返回后失效

// 错误写法int*createValue(){intx=42;return&x;// 返回局部变量的地址——悬空指针!}// 正确写法一:返回变量值(非指针)intcreateValue(){return42;}// 正确写法二:如果确实需要指针,用动态内存(第 19 篇会讲)// 或者让调用者传入一个变量的地址voidfillValue(int*p){*p=42;// 安全:修改的是调用者的变量}

错误5:使用 scanf 时对基本类型变量忘了加 &

intage;scanf("%d",&age);// 正确:age 前加 &// 原因:scanf 需要知道"把数据存到哪",所以需要变量的地址charname[20];scanf("%19s",name);// 正确:name 前不加 &,但必须限制宽度// 原因:数组名本身就是地址(第 12 篇详细讲),%19s 防止溢出

八、练习题

练习题1:指针基本操作

写出下面程序的输出:

#include<stdio.h>intmain(void){intx=5,y=10;int*p=&x;*p=y;p=&y;*p=30;printf("x = %d, y = %d\n",x,y);return0;}

不要运行,先用纸笔推导出结果,再上机验证。

练习题2:通过指针交换两个数

写一个swap函数,通过指针交换两个整数的值。函数内部允许使用临时变量temp。在main函数中定义两个整数,调用swap交换它们,然后在main中打印交换后的结果,确认值真的被交换了。

函数声明参考:void swap(int *a, int *b)

练习题3:遍历与修改

定义一个包含 6 个元素的double数组:{1.5, 2.5, 3.5, 4.5, 5.5, 6.5}

  1. 使用指针遍历这个数组,打印每个元素的值和地址
  2. 使用指针把每个元素的值都加上 0.5
  3. 再次遍历打印修改后的结果
  4. 观察地址的变化,确认double指针每次 +1 地址增加了多少

九、本篇总结

  1. 指针就是存地址的变量。普通变量存数据,指针变量存"另一个数据的地址"
  2. & 取地址,解引用*:&a问"a 在哪",*p去 p 指的地址"看里面有什么"
  3. 指针类型决定了运算步长int *pp+1跳 4 字节,char *p跳 1 字节,double *p跳 8 字节
  4. 永远不要使用未初始化的指针:它不是语法错误,但会让程序出现随机行为。要么初始化为&变量,要么初始化为NULL
  5. 空指针更容易排查,野指针更隐蔽:NULL 解引用通常会很快暴露问题,而野指针可能潜伏很久才出错

http://www.zskr.cn/news/1361672.html

相关文章:

  • 2025-2026年时余家具电话查询:选购前需核实产品材质与风格适配 - 品牌推荐
  • AI 辅助用户画像与场景构建:从访谈文本到可验证的研究假设
  • AI 开发工具选择指南:Qoder、Qwen 与开发者使用策略
  • 前端全流程求职Skill 攻略
  • 2026年论文党必备:盘点2026年倾心之选的的降AIGC网站
  • 政务管理领域大模型应用场景
  • 2026年常压快开人孔权威厂商评测:蛭石隔热管托/隔热管托/可变式弹簧支吊架/固定支吊架/坐式管托/垂直吊盖人孔/选择指南 - 优质品牌商家
  • 通过curl命令调试Taotoken大模型API,快速排查接入问题
  • 水纹真实度提升300%的关键技巧,深度拆解--style raw、--chaos 45与自定义tile texture协同机制
  • 问题不是要不要审,而是审查放在哪条路径
  • 2026年重庆阳台改造优选指南:七维评估模型筛选出的6家靠谱企业 - 优家闲谈
  • Midjourney渐变美学的神经渲染原理(附RGB-HSV-LCH三空间渐变映射对照表·行业首曝)
  • 为什么头部科技公司已停用公有版Midjourney?企业版专属水印、审计日志与API策略深度解密
  • 施工现场安全事故预警准确率达94.6%?——解密某央企AI Agent边缘计算部署架构与3个月落地实录
  • 为什么你的AI Agent总在跨境清关环节“失语”?揭秘NLP+规则引擎混合推理的5个关键断点
  • Lindy流程自动化实施倒计时手册:仅剩最后23家企业获赠官方认证治理框架V2.3(含审计就绪检查表)
  • 镜像视界浙江科技有限公司|数字孪生・视频孪生・无感定位・跨镜追踪 技术地位与核心优势
  • Go语言表驱动测试:测试数据组织
  • 【Midjourney渐变风格终极指南】:20年AI视觉专家亲授7大高阶参数组合与色彩过渡黄金公式
  • 让 AI 做代码 Review(CR):测试如何提前在代码提交阶段发现 Bug?
  • 新能源预测核心名词解释
  • OpenClaw本地Agent网关机器人对接全解析:技能MCPRAG分层搞定!
  • 【Java 抽象类(零基础完整版超详细教程)看完彻底弄懂 】
  • 美国景观变化监测系统:1985-2025年美国本土及海外地区的年度遥感监测数据,包含30米分辨率的变化、土地覆盖和土地利用三类产品
  • 深度强化学习与控制2026 课程总结Week2
  • 2026年腾讯云OpenClaw/Hermes Agent配置Token Plan怎么安装看这
  • TVA驱动智能家居的视觉范式革命(11)
  • 2026.5.20,2026.5.21笔记
  • 从手工报表到实时BI:一个零售数据平台的踩坑与重构实战
  • 项目介绍 基于Python的大学生竞赛组队系统设计与实现(含模型描述及部分示例代码)专栏近期有大量优惠 还请多多点一下关注 加油 谢谢 你的鼓励是我前行的动力 谢谢支持 加油 谢谢