1

这是一个简单的程序来解释我的意思。给定长度 n,它初始化标准输入读取的 n 个整数序列。

int n, *seq, *current;
scanf("%d", &n);
seq = malloc(n*sizeof(int));
for (current = seq; current - seq < n; current++)
  scanf("%d", current);

我的疑问是最后一个增量current使它指向分配的内存之外的东西。显然,从该位置读取是错误的。但是如果我不读那个位置怎么办?

该程序运行正确,但我的问题是:这是一种标准且良好的做法,还是可能会引起麻烦并且应该避免的事情?

更新:那么将其附加到上一个程序的末尾呢?

for (current--; current - seq >= 0; current--)
  printf("%d\n", *current);

根据@MOHAMED的回答,这是错误的,不是因为它是对无效位置的访问,而是因为current - seq >= 0当指向第一个元素之前的一个位置时可能会给出错误的结果current,因此具有未定义的值!

4

3 回答 3

6

从这个话题

是的,允许指针指向刚刚超过数组末尾的位置。但是,您不允许尊重这样的指针。

C99 6.5.6/8 加法运算符(已添加重点)

如果表达式 P 指向数组对象的最后一个元素,则表达式 (P)+1 指向数组对象的最后一个元素,如果表达式 Q 指向数组对象的最后一个元素,则表达式(Q)-1 指向数组对象的最后一个元素。如果指针操作数和结果都指向同一个数组对象的元素,或者超过数组对象的最后一个元素,则计算不应产生溢出;否则,行为未定义。如果结果指向数组对象的最后一个元素,则不应将其用作计算的一元 * 运算符的操作数。

关于您的更新

并根据这个主题

在您的情况下,比较current - seq >= 0未定义的行为:当它等于 时,在迭代后递减current - seq时变为未定义。currentseq

标准第 6.5.6 节第 8 部分对此进行了介绍:

当一个整数类型的表达式被添加到指针或从指针中减去时,结果具有指针操作数的类型。如果指针操作数指向数组对象的元素,并且数组足够大,则结果指向与原始元素偏移的元素,使得结果和原始数组元素的下标之差等于整数表达式。换句话说,如果表达式P指向数组对象的第 i 个元素,则表达式((P)+N等价地,N+(P))和(P)-N(其中N的值为n)分别指向数组对象的第它们存在。此外,如果表达式i+ni−nP指向数组对象的最后一个元素,表达式(P)+1指向数组对象的最后一个元素,如果表达式Q指向数组对象的最后一个元素,则表达式(Q)-1指向数组对象的最后一个元素。如果指针操作数和结果都指向同一个数组对象的元素,或者超过数组对象的最后一个元素,则计算不应产生溢出;否则,行为是 undefined。如果结果指向数组对象的最后一个元素,则不应将其用作计算的一元运算符的操作数*

该标准的长度涵盖了数组对象最后一个元素之后位置处的元素,而第一个元素之前位置处的元素属于上述规则的“否则”子句。

于 2013-11-01T08:43:07.840 回答
2

如果您不再使用指针(除非您重新分配它),那么没关系。

仅仅拥有一个指针不会导致未定义的行为,而是何时以及如何使用它会导致问题。所以如果你不使用它,什么都不会发生。

于 2013-11-01T08:40:54.673 回答
0

很好,但以下内容可能更清晰,更不容易出错:

int n, *seq, counter;
scanf("%d", &n);
seq = malloc(n*sizeof(int));
for (counter = 0; counter < n; counter++)
  scanf("%d", &seq[counter]);
于 2013-11-01T08:44:30.987 回答