关于非数组变量进行指针算术运算的合法性咨询
指针算术在非数组变量上的合法性分析
好问题!这确实是C/C++里容易搞混的指针算术规则点,咱来把它掰扯清楚:
首先得明确标准里的核心规定:指针算术只有在以下场景下才是有定义的行为:
- 指针指向同一个数组对象的元素(包括数组末尾的“哨兵”位置,也就是数组最后一个元素的下一个地址);
- 单个变量可以被视为长度为1的数组,所以指向单个变量的指针可以参与有限的指针算术。
接下来针对你提到的两个具体例子逐一分析:
1. 两个独立变量的指针相减(d - c)
比如这段代码:
int a=10; int b=20; int* c=&a; int* d=&b; int e = d - c;
这两个指针c和d指向的是完全独立的对象,不属于同一个数组(哪怕把单个变量看作长度为1的数组,这也是两个完全不同的“数组”)。这种情况下,指针相减的操作属于未定义行为。
虽然有些编译器在实际运行时会返回一个看似合理的数值(比如两个地址的差值除以sizeof(int)),但这只是编译器的实现细节,标准完全不保证任何结果——换个编译器、调整优化级别,甚至只是修改代码的其他部分,都可能导致程序崩溃、输出奇怪的数值,或者出现其他不可预料的问题。
2. 单个变量的指针加1(c + 1)
再看这段代码:
int a=10; int* c=&a; int* e = c + 1;
这里c指向单个变量a,按照标准可以视为指向长度为1的数组的第一个元素。那么c + 1会指向这个“数组”的末尾位置(也就是a之后的内存地址),这个单纯的指针加法操作是合法的(有定义的)。
但要特别注意:你绝对不能解引用e(也就是不能写*e),因为这个地址不属于任何有效的对象,解引用会立刻触发未定义行为。只是获取这个地址本身是允许的,但不能对它进行读写操作。
为什么会有矛盾信息?
出现矛盾的原因主要是“编译器实现行为”和“标准规定”的差异:有些编译器为了方便调试或者兼容旧代码,会对这类未定义行为做“宽容”处理,让程序看起来能正常运行,但这并不代表这种写法是正确的。在生产环境或者严格遵循标准的代码里,必须杜绝依赖这种未定义行为的写法。
内容的提问来源于stack exchange,提问作者fibo11235
相关产品推荐
相关产品推荐

