结构体指针声明为point* p;,初始化须严格匹配类型且确保内存有效:堆上用new point{1,2},栈上用&pt并注意生命周期;访问成员时变量用.、指针用->;const位置决定指针或所指内容是否可变。

结构体指针怎么声明和初始化
结构体指针不是“结构体的地址”这种模糊说法,而是明确指向某块内存的变量,类型必须严格匹配。常见错误是直接用 & 取局部结构体地址后返回,或者忘记分配内存就解引用。
-
struct Point { int x, y; };定义后,Point* p;是声明,但此时p是野指针,不能直接用-> - 初始化推荐两种方式:
Point* p = new Point{1, 2};(堆上),或Point pt{3, 4}; Point* p = &pt;(栈上,注意生命周期) - 用
malloc或calloc初始化时,必须强制转成结构体指针类型:Point* p = (Point*)malloc(sizeof(Point));,否则编译可能不报错但行为未定义
成员访问运算符 -> 和 . 到底怎么选
核心就一条:左边是结构体变量用 .,是结构体指针用 ->。混淆本质是搞混了操作数类型,不是记不住符号。
-
Point p1{5, 6}; p1.x→ 正确;p1->x→ 编译错误:error: base operand of '->' has non-pointer type 'Point' -
Point* p2 = &p1; p2->x→ 正确;p2.x→ 编译错误:error: request for member 'x' in 'p2', which is of pointer type 'Point*' (maybe you meant to use '->' ?) - 嵌套结构体里容易出错:
struct Rect { Point top_left; }; Rect r; r.top_left.x是合法的,但Rect* pr = &r; pr->top_left.x才对;写成pr->top_left->x就错——因为top_left是值类型,不是指针
结构体指针传参时,. 和 -> 的陷阱
函数参数是结构体指针时,内部访问必须统一用 ->,哪怕你习惯性写了 .,编译器也不会帮你“自动转”,只会报错。
- 函数签名如
void print_point(Point* p),函数体内只能写p->x,写p.x直接编译失败 - 如果误传了结构体变量而非指针(比如调用
print_point(p1)而非print_point(&p1)),GCC/Clang 会提示:cannot convert 'Point' to 'Point*' in argument - C++ 中更推荐用引用传参避免裸指针歧义:
void print_point(const Point& p),这时用p.x,语义清晰且不用操心空指针
结构体指针和 const 的组合容易翻车
const 出现在指针声明不同位置,含义完全不同,一不留神就改不了值或删不掉对象。
立即学习“C++免费学习笔记(深入)”;
-
const Point* p;→ 指针可变,指向内容不可变(不能通过p->x = 10修改) -
Point* const p = &pt;→ 指针不可变(不能p++或重新赋值),但内容可改 -
const Point* const p = &pt;→ 都不可变,最安全也最受限 - 用
new分配后忘了delete,或用const Point* p = new Point;后无法delete p;(因类型不匹配),这是典型的内存泄漏+编译报错组合
结构体指针本身不难,真正卡住人的永远是类型匹配、生命周期和 const 修饰位置这三处。写完记得检查:指针有没有初始化、访问符跟操作数类型对不对、const 放在哪儿、释放时机有没有失控。










