小熊奶糖(BearCandy)
小熊奶糖(BearCandy)
发布于 2025-11-11 / 3 阅读
0
0

C语言取地址符&和解引用符*优先级详解

核心结论

  • 优先级相同:取地址符 & 和解引用符 * 的优先级相同
  • 结合性从右向左结合
  • 重要对比:后缀操作符([]()->.)的优先级高于 &*

基本概念

运算符 名称 作用 示例
& 取地址符 获取变量的内存地址 &x 返回变量x的地址
* 解引用符 访问指针指向的内存内容 *p 返回指针p指向的值

优先级规则详解

1. 与后缀操作符的优先级比较

规则:后缀操作符优先级 > &和*优先级

示例分析

int arr[] = {10, 20, 30};
int *p = arr;

情况1:*p++

int value = *p++;
// 等价于:*(p++)
// 执行顺序:
// 1. p++ 先返回p的当前值(指向arr[0]),然后p自增指向arr[1]
// 2. * 对返回的地址解引用,得到arr[0]的值10
// 结果:value = 10, p指向arr[1]

情况2:(*p)++

int value = (*p)++;
// 执行顺序:
// 1. (*p) 先解引用得到arr[0]的值10
// 2. ++ 将该值增加,arr[0]变为11
// 结果:value = 10, arr[0]的值变为11

情况3:&arr[1]

int *ptr = &arr[1];
// 等价于:&(arr[1])
// 执行顺序:
// 1. arr[1] 先访问数组第二个元素
// 2. & 取该元素的地址
// 结果:ptr指向arr[1]

2. 连续使用&和*(从右向左结合)

规则:多个&和*连续出现时,从最右边开始计算

示例分析

int a = 100;
int *p = &a;      // p指向a
int **pp = &p;    // pp指向p

情况1:**pp

int value = **pp;
// 等价于:*(*pp)
// 执行顺序:
// 1. *pp 解引用得到p(即a的地址)
// 2. *(*pp) 再次解引用得到a的值100
// 结果:value = 100

情况2:&*p

int *q = &*p;
// 等价于:&(*p)
// 执行顺序:
// 1. *p 解引用得到变量a
// 2. &(*p) 对a取地址,结果等于p
// 结果:q的值与p相同,都指向a

常见应用场景

1. 函数中修改指针本身

void allocateMemory(int **ptr) {
    *ptr = (int*)malloc(sizeof(int));  // 修改外部指针的指向
    **ptr = 123;                       // 修改指针指向的值
}

int main() {
    int *myPtr = NULL;
    allocateMemory(&myPtr);  // 传递指针的地址
    printf("%d\n", *myPtr);  // 输出:123
    free(myPtr);
    return 0;
}

2. 多级指针与字符串数组

char *names[] = {"Alice", "Bob", "Charlie"};
char **pp = names;  // pp指向names[0]

// 获取"Bob"的第一个字符'B'
char first_char = *(*(pp + 1));
// 等价于:pp[1][0]

// 执行顺序:
// 1. pp + 1 指向names[1]
// 2. *(pp + 1) 解引用得到names[1](指向"Bob"的指针)
// 3. *(*(pp + 1)) 再次解引用得到'B'

易错点总结

表达式 实际含义 常见误解
*p++ *(p++) 指针先移动,再取值
*p->data *(p->data) 先访问成员,再解引用
&arr[i] &(arr[i]) 先取元素,再取地址
**pp *(*pp) 从右向左解引用

最佳实践

  1. 多用括号:在复杂表达式中使用括号明确优先级
  2. 分步编写:将复杂表达式拆分成多行,提高可读性
  3. 注释说明:对复杂的指针操作添加注释
// 不推荐:难以理解
int result = **++pp;

// 推荐:清晰明确
pp++;                    // 移动到下一个指针
int result = **pp;       // 获取指向的值

// 或者使用括号
int result = *(*(++pp));

记忆技巧

  • 后缀优先[] ()-> . 总是先执行
  • 向右看齐&*从右向左计算
  • 括号是友:不确定时就加括号

掌握这些规则后,面对复杂的指针表达式时就能游刃有余地分析了。


评论