是否可以向后迭代到数组开头之前的一处

发布于 2024-12-14 06:28:18 字数 1448 浏览 0 评论 0原文

例如,如果我有一个指向字符串的 ptr 并将 ptr 移动到字符串中的最后一个字符,并使用 *p-- 向后迭代到字符串的开头,并且我迭代到在数组开始之前定位一个,这样可以吗?或者我会遇到访问冲突吗?我只是移动指针 - 不访问。它似乎在我的代码中工作,所以想知道这是否是不好的做法?

这是一个示例 - 行 *next-- = rem + 'A';我想问一下是否可以???

#include <stdio.h>     /* printf */
#include <string.h>    /* strlen, strcpy */
#include <stdlib.h>    /* malloc/free */
#include <math.h>      /* pow */

/* AAAAA (or whatever length) = 0, to ZZZZZ.  base 26 numbering system */
static void getNextString(const char* prev, char* next) {
   int count = 0;
   char tmpch = 0;

   int length = strlen(prev);
   int i = 0;
   while((tmpch = *prev++) != 0) {
      count += (tmpch - 'A') * (int)pow(26.0, length - i - 1);
      ++i;
   }

   /* assume all strings are uppercase eg AAAAA */
   ++count;

   /*if count above ZZZ... then reset to AAA... */
   if( count >= (int)pow(26.0, length))
      count = 0;

   next += (length-1);  /* seek to last char in string */
   while(i-- > 0) {
      int rem = count % 26;
      count /= 26;
      *next-- = rem + 'A';   /*pntr positioned on 1 before array on last iteration - is OK? */
   }
}

int main(int argc, char* argv[])
{
   int buffsize = 5;
   char* buff = (char*)malloc(buffsize+1);

   strcpy(buff, "AAAAA");
   int iterations = 100;

   while(--iterations){
      getNextString(buff, buff);
      printf("iteration: %d buffer: %s\n", iterations, buff);
   }

   free(buff);
    return 0;
}

If for example I have a ptr to a string and move ptr to last character in string and iterate backwards to beginning of string using *p-- and I iterate to position one before start of array is this OK? Or will I get an access violation? I am only moving pointer - not accessing. It seems to work in my code so wondering if it is bad practice or not?

Here is a sample - line with *next-- = rem + 'A'; is one I am questioning if ok???

#include <stdio.h>     /* printf */
#include <string.h>    /* strlen, strcpy */
#include <stdlib.h>    /* malloc/free */
#include <math.h>      /* pow */

/* AAAAA (or whatever length) = 0, to ZZZZZ.  base 26 numbering system */
static void getNextString(const char* prev, char* next) {
   int count = 0;
   char tmpch = 0;

   int length = strlen(prev);
   int i = 0;
   while((tmpch = *prev++) != 0) {
      count += (tmpch - 'A') * (int)pow(26.0, length - i - 1);
      ++i;
   }

   /* assume all strings are uppercase eg AAAAA */
   ++count;

   /*if count above ZZZ... then reset to AAA... */
   if( count >= (int)pow(26.0, length))
      count = 0;

   next += (length-1);  /* seek to last char in string */
   while(i-- > 0) {
      int rem = count % 26;
      count /= 26;
      *next-- = rem + 'A';   /*pntr positioned on 1 before array on last iteration - is OK? */
   }
}

int main(int argc, char* argv[])
{
   int buffsize = 5;
   char* buff = (char*)malloc(buffsize+1);

   strcpy(buff, "AAAAA");
   int iterations = 100;

   while(--iterations){
      getNextString(buff, buff);
      printf("iteration: %d buffer: %s\n", iterations, buff);
   }

   free(buff);
    return 0;
}

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(5

拒绝两难 2024-12-21 06:28:18

根据以下 C-FAQ question\answer,我引用:

仅当指针指向时才定义指针算术
在同一分配的内存块内,或到虚构的
“终止”元素超过它;否则,行为是
未定义,即使指针没有取消引用

所以我的答案是,在数组开头之前进行迭代是不行的。

还有对 C 标准的引用:

  • K&R2 Sec。 5.3 页。 100,秒。 5.4 第 102-3 页,第 2 节A7.7 页。
    205-6
  • ISO 秒。 6.3.6 (C89) 或 6.5.6/8 (C99)
  • 基本原理部分3.2.2.3

According to the following C-FAQ question\answer, and I quote:

Pointer arithmetic is defined only as long as the pointer points
within the same allocated block of memory, or to the imaginary
``terminating'' element one past it; otherwise, the behavior is
undefined, even if the pointer is not dereferenced.

So my answer would be no, it is not OK to iterate before the beginning of an array.

There are references to the C standards as well:

  • K&R2 Sec. 5.3 p. 100, Sec. 5.4 pp. 102-3, Sec. A7.7 pp.
    205-6
  • ISO Sec. 6.3.6 (C89) or 6.5.6/8 (C99)
  • Rationale Sec. 3.2.2.3
又爬满兰若 2024-12-21 06:28:18

只要您不尝试从该地址读取或写入,就不会导致违规。这是因为 ptr 中的值只是另一个数字。

As long as you don't try to read or write from that address, it won't cause a violation. This is becuase the value in a ptr is just another number.

梦中楼上月下 2024-12-21 06:28:18

您的代码正常工作的唯一原因是您的长度恰好小于或等于 i 中的初始值。

我个人不想依赖这个,因为我知道我会忘记这个特定的条件,并且我会做出一些修改来破坏它。因此,虽然它在技术上可行,但这并不是一个好主意。

The only reason your code is working is that your length happens to be less than or equal to the initial value in i.

I personally would not want to rely on this, since I know I'd forget about that particular condition, and I'd make some modification that broke it. So while it technically works, it's not really a good idea.

花之痕靓丽 2024-12-21 06:28:18

[expr.add], ¶5

如果指针操作数和结果都指向同一个数组对象的元素,或者过去的一个
数组对象的最后一个元素,求值不会产生溢出;否则,行为是
未定义。

所以它是 UB,因为结果不指向数组的任何有效元素。

[expr.add], ¶5

If both the pointer operand and the result point to elements of the same array object, or one past
the last element of the array object, the evaluation shall not produce an overflow; otherwise, the behavior is
undefined.

So it's UB, since the result do not point to any valid element of the array.

眼泪也成诗 2024-12-21 06:28:18

评论,实际上:(对 FelixCQ 的回答)

我可以理解为什么在循环中获取超出范围的指针可能会很危险,因为可能会展开循环和乱序求值,因此在评估终止条件之前,指针可能会被解除引用,如这个简单的示例所示:

for (char* tmp = s+len; tmp >= s; tmp--) sum += *tmp;

但是,如果这是 UB 的原因,则

for (int i = len; i >= 0; i--) sum += s[i];

存在完全相同的问题!或者我错过了什么?

comment, acctually: (to FelixCQ's answer)

I could understand why obtaining an Out-of-range pointer in a loop could be dangerous because of possible loop unrolling and out-of-order evaluation, so that the pointer could get derefferenced before the terminating condition is evaluated, as in this simple example:

for (char* tmp = s+len; tmp >= s; tmp--) sum += *tmp;

However, if this is the reason for UB, then

for (int i = len; i >= 0; i--) sum += s[i];

has exactly the same problem! Or am I missing something?

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文