🌱类型转换指针作为参数和作为赋值目标的区别
遇到一个场景,结构体B中包含有结构体A的匿名成员,需要单独对一个 B* 初始化其中的 A* 部分。
情况1
如果把类型转换后的指针作为函数参数,实际上是将内存地址传递给函数,函数通过这个地址修改内存内容,不需要修改指针变量本身。此时代码是这样的:
typdef struct A{
int x;
int y;
} A;
typedef struct B{
struct A;
int z;
}
void initA(A* ptr){
ptr->x = 0;
ptr->y = 0;
}
int main(int argc, char** argv){
B* b = (B*)malloc(sizeof(B));
initA((A*)b);
}
因为传入的参数 (A*)b 修改的是指针类型,而不是指针指向的地址,所以这是安全的,也能部分初始化B中的属于A的部分。
情况2
如果把类型转换后的指针作为赋值左值,也就是会试图修改指针变量本身,这时候代码是这样的:
A* newA(){
return (A*)malloc(sizeof(A));
}
int main(int argc, char** argv){
B* b = (B*)malloc(sizeof(B));
(A*)b = newA();
}
不幸的是,这样的代码是无法按照预期工作的,因为 (A*)b 是一个右值,是一个临时表达式,它的值无法被修改。
总结
本质的区别在于,一个用法是使用指针指向的地址,此时类型转换不会对效果产生印象;一个是修改指针指向的地址本身,这是需要警惕的一种操作,因为可能会导致内存泄漏等问题。