解引用运算符 * 和取地址运算符 & 是C语言中内存操作的基本工具。它们允许对内存中的数据进行直接管理,这使得C语言成为系统编程的流行选择。
问题历史:
自从C语言在1970年代问世以来,它的哲学就与低级内存管理密切相关。运算符 * 和 & 实现了在处理器级别上使用的间接寻址技术,因此可以使用指针,动态分配内存,创建高效的数据结构。
问题: 错误使用这些运算符会导致许多bug:内存泄漏、数据损坏、段错误。编译器并不总是明确地警告这些错误,特别是当指针类型大小相同但内容不同的情况下。
解决方案: 仔细关注指针类型,跟踪分配内存的生命周期,进行初始化和正确释放,并检查解引用操作和使用的地址的正确性。
代码示例:
int x = 10; int *p = &x; // 取地址 int y = *p; // 解引用(获取地址中的值) // 与数组指针的操作 int arr[3] = {1,2,3}; int *pa = arr; printf("%d", *(pa+1)); // 数组的第二个元素
关键特性:
可以取临时变量的地址,例如:& (x + y) 吗?
不可以,表达式的地址不能被取得,因为表达式的结果不是内存对象。只有变量、数组或结构体的地址才能被取得。
代码示例:
int z = 5; int p = &(z + 1); // 编译错误
解引用void指针有什么不同?
类型为 void * 的指针不能直接解引用,必须先将其转换为具体类型。这是一个通用指针,但在明确转换后才能进行与类型无关的解引用操作:
void *pv = &x; int value = *(int*)pv; // OK
可以解引用空指针(NULL)吗?
不可以,这会导致未定义行为——内存损坏或程序崩溃。在解引用之前,请始终检查指针:
int *ptr = NULL; if (ptr) { *ptr = 10; // 从不执行 }
开发人员在函数中取局部变量地址,然后将其返回,随后在调用代码中解引用指针。
优点:
缺点:
使用动态分配内存为变量分配空间,地址返回给调用代码,并在最后通过free释放。
优点:
缺点: