C语言指针基础疑问:*取值规则、指针偏移运算相关问题
C语言指针相关疑问解答
先贴出示例代码方便对照:
int x = 3; int *y = &x; int z = *y; printf("%d", z); //疑问1:为什么输出数值而非地址? int *u= (y+1); //疑问2:这行代码代表什么含义? printf("%d", *u); //疑问3:为什么这行输出结果是3?
疑问1解答:为什么打印z得到数值而非地址
推导错误的核心是混淆了*符号在两个场景下的完全不同作用:
- 当
*出现在变量声明语句里、和类型名相邻时,它是类型标记,用来声明当前变量是指针类型,不是运算操作符。比如int *y = &x;这行的真实逻辑是:声明一个int*(指向int的指针)类型的变量y,把x的内存地址赋值给y本身,不要错误把声明语句的语法拆成*y = &x理解。 - 当
*出现在已经声明完成的指针变量前面时,它是解引用操作符,作用是顺着指针存储的地址,找到对应内存块里存储的实际值。
对应到int z = *y;这行,y里存的是x的地址,*y就是解引用拿到x存储的值3,把整数3赋值给int类型的z,z本身就是普通整型变量,打印出来自然是数值3,和地址没有关系。
疑问2解答:int *u= (y+1);的含义
这行是声明一个新的int*类型指针u,给u赋值为y+1的计算结果。
C语言里指针的加减运算不是直接在地址数值上加1,而是会按照指针指向的类型长度做偏移:y是指向int的指针,y+1就代表从y存储的原地址开始,向后偏移1个int类型长度(通常32位环境下是4字节,64位环境下int长度和编译器实现有关)的内存位置。最终u会指向这个偏移后的、没有经过主动申请使用权限的内存地址。
疑问3解答:为什么打印*u得到3
这个输出结果是完全随机的未定义行为,没有任何必然性,当前运行得到3只是巧合:
你没有申请过y+1对应内存位置的使用权,这块内存里存的内容是不受程序控制的——可能是栈上之前运行残留的临时值,可能是编译器内存对齐填充的默认值,甚至可能是系统保留的敏感数据。这次运行看到3,换个编译选项、加几行无关代码、换个系统运行,结果可能变成乱码、随机数,甚至直接触发程序崩溃。这种越界访问内存的写法是C语言指针操作的典型错误,运行结果没有任何实际参考价值。
指针操作核心注意点:解引用指针前,一定要确认指针指向的是合法申请、可以正常访问的内存块,不要随意对未初始化、越界偏移的指针做解引用操作。
内容的提问来源于stack exchange,提问作者beginner
相关产品推荐
相关产品推荐

