可变借用
C 里,拿到 T * 通常意味着“可以改”。问题是,C 不阻止你同时留下很多入口:
uint8_t *a = buf;
uint8_t *b = buf;
a[0] = 1;
printf("%u\n", b[0]);
这段代码本身没错,但在真实项目里,多个指针同时读写同一块数据,会让状态变化很难追踪。谁刚刚改过?谁还拿着旧视图?某个函数会不会在你读之前顺手改了?
阅读更多C 里,拿到 T * 通常意味着“可以改”。问题是,C 不阻止你同时留下很多入口:
uint8_t *a = buf;
uint8_t *b = buf;
a[0] = 1;
printf("%u\n", b[0]);
这段代码本身没错,但在真实项目里,多个指针同时读写同一块数据,会让状态变化很难追踪。谁刚刚改过?谁还拿着旧视图?某个函数会不会在你读之前顺手改了?
阅读更多C 里的 T * 太常用了。它可以表示很多不同语义:
void print_config(const struct Config *cfg);
void reset_config(struct Config *cfg);
int parse_packet(const uint8_t *data, size_t len, struct Packet *out);
void driver_write(void *addr, uint32_t value);
这些在 C 里都长得像指针,但语义完全不同:
Rust 不会把这些都塞进一个“指针”概念里。第一层可以先用这张表:
阅读更多C 开发者第一次看到 lifetime,很容易以为它是在给对象标注“活多久”。
这个理解不准确。
Rust 的 lifetime 不是运行时计时器,也不是对象真实存活时间的手写说明。它更像编译器用来检查引用关系的一套静态约束:一个引用不能比它指向的数据活得更久。
阅读更多上一篇讲所有权:谁拥有,谁释放。
但大多数函数并不想接管资源。它只是想临时看一眼数据,或者临时改一下数据。C 里通常传指针:
void inspect(const uint8_t *buf, size_t len);
void update(uint8_t *buf, size_t len);
Rust 里对应的是借用:
fn inspect(buf: &[u8]) {}
fn update(buf: &mut [u8]) {}
借用的核心不是“Rust 指针语法”,而是访问权限:不拿走所有权,只临时读或写。
阅读更多