在我的机器上递减NULL指针仍然会提供NULL指针,我想知道这是否定义正确。
char *p = NULL;
--p;
答案 0 :(得分:6)
是的,行为是不确定的。
--p
等效于p = p - 1
(除了p
仅被评估一次,在这种情况下无关紧要)。
N1570 6.5.6第8段,讨论加法运算符,表示:
将具有整数类型的表达式添加或减去时 从指针开始,结果具有指针操作数的类型。如果 指针操作数指向数组对象的元素,并且该数组 足够大,结果指向的元素与 原始元素,使得下标的差异 结果数组元素和原始数组元素等于整数表达式。
[...]
如果指针操作数和结果都指向元素 相同的数组对象,或者在数组的最后一个元素之后 目标,评估不得产生溢出;否则, 行为是不确定的。
由于指针值p
不指向数组对象的元素,也不指向数组对象的最后一个元素,因此p - 1
的行为是不确定的。
(顺便说一句,如果您的代码导致p
为空指针,我会感到很惊讶-尽管由于行为是不确定的,所以语言肯定允许它。我可以想象一个优化编译器忽略{{1 }},因为它知道其行为是不确定的,但我自己还没有看到。您怎么知道--p;
为空?)
答案 1 :(得分:-1)
据我在GCC上看到的,它不会生成空指针。减少就是减去一个数字。随着下溢,数字就回绕了。您可以在这里看到。
import random
roll = random.randint(1, 6) + random.randint(1, 6)
numbers = roll == 1 or roll == 4 or roll == 5 or roll == 6 or roll == 8 or roll == 9 or roll == 10
while True:
if roll == 7 or roll == 11:
print('nice')
break
elif roll == 3 or roll == 2 or roll == 12:
print('crapped out')
break
elif numbers:
print('your number is:', roll, "roll again...")
break
输出为
#include "stdio.h"
#include <inttypes.h>
int main()
{
char *p = NULL;
printf("%zx\n", (uintptr_t)p);
--p;
printf("%zx\n", (uintptr_t)p);
}