如果不使用它,是否可以指向无效位置?

时间:2013-11-01 08:39:18

标签: c ansi

这是一个简单的程序来解释我的意思。给定长度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可能会给出错误的结果,因此具有未定义的值!

3 个答案:

答案 0 :(得分:6)

从此topic

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

  

C99 6.5.6 / 8加法运算符(重点补充)

     

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

关于您的更新

根据这个topic

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

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

  

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

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

答案 1 :(得分:2)

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

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

答案 2 :(得分:0)

没关系,但以下内容可能更清晰,更不容易出错:

int n, *seq, counter;
scanf("%d", &n);
seq = malloc(n*sizeof(int));
for (counter = 0; counter < n; counter++)
  scanf("%d", &seq[counter]);