【问题标题】:What is happening with this arithmetic expression involving pointers?这个涉及指针的算术表达式发生了什么?
【发布时间】:2015-08-24 13:17:28
【问题描述】:

这是 C 中的代码:

#define ALLOCSIZE 1000 /* size of available space */

static char allocbuf[ALLOCSIZE]; /* storage for alloc */
static char *allocp = allocbuf; /* next free position */

char *alloc(int n) /* return pointer to n characters */
{
    if (allocbuf + ALLOCSIZE - allocp >= n) { /* it fits */
        ...
    }
}

我不明白以下表达式中发生了什么:

allocbuf + ALLOCSIZE - allocp >= n

我知道allocbuf作为一个数组名相当于一个指向第一个元素&allocbuf[0]的指针,而显然allocp是一个指针,最后说ALLOCSIZE是一个简单的int。因此,将 ALLOCSIZE 添加到 allocbuff 会得到 allocbuff 的 ALLOCSIZE 索引元素,它也是一个指针。但是从指针 &allocbuf[ALLOCSIZE] 中减去指针 allocp 是我迷路的地方。我什至不确定是否可以在 C 中添加指针。

请告诉我我在哪里错了或者我在这个解释中遗漏了什么。

这个程序的重点是存储字符。

【问题讨论】:

  • 您不能添加指针,但可以减去它们以获得距离(以对象数为单位)。想想allocbuf + ALLOCSIZE - allocbuf。结果如预期 - ALLOCSIZE.
  • 两个指针b - a之差是ab之间的元素个数。所以,allocbuf - allocp-1 乘以已分配的元素数。
  • ifif (ALLOCSIZE >= n) 相同。无法添加指针,因为它没有意义。但是,它可以被减去。 (谷歌“减去指针 c”以获取更多信息)
  • @CoolGuy 鉴于 allocp 永远不会改变,是的,但这可能是一个糟糕的假设。

标签: c pointers


【解决方案1】:

代码是一个固定缓冲区分配器,并且正在检查以确保您至少有 n 字节剩余。它有助于以图形方式查看事物,我所说的图形是指 MSPaint:

所以分解表达式:

allocbuf + ALLOCSIZE - allocp >= n

allocbuf + ALLOCSIZE 是数组的结尾。 end 和allocp 之间的区别是剩余字节数。所以我们只是检查以确保差异至少为n

减去两个指针,只要它们指向同一个数组中的元素(或过去一个),就很好地定义为它们之间的元素个数。举个更简单的例子,allocbufallocbuf + ALLOCSIZE 都是指针(char* 类型),(allocbuf + ALLOCSIZE) - allocbuf == ALLOCSIZE 是它们之间的元素数量(在这种情况下为char)。

【讨论】:

    【解决方案2】:

    从指针中减去指针会给你(如果它们兼容)它们之间的元素数量(大小由指针指向的类型决定)。

    所以:

    allocbuf + ALLOCSIZE
    

    指向allocbuf最后一个元素的指针

    allocbuf + ALLOCSIZE - allocp
    

    allcobuf 的最后一个元素 (+ 1) 和 allocp 之间剩余的元素数量

    在这种情况下:

    allocbuf + ALLOCSIZE - allocp >= n
    

    确定allocbuf 中是否留有足够的元素以容纳n 元素。

    编辑:

    您可以将其与数组进行比较: 如果您有指向第一个元素的指针(将使用0 进行索引)和第二个指针,该指针进一步指向元素大小的 4 倍(将指向以 4 为索引的第 5 个元素),那么当您减去这两个时将在它们之间获得 4 个元素(例如从索引 4 中减去索引 0)。但只有当指针指向同一个内存缓冲区时(如数组)才有意义。

    所以这个:

    int array[5] = {1, 2, 3, 4, 5, 6};
    int a* = &array[0] //equivalent to array
    int b* = &array[4]
    

    还有这个:

    int *array = malloc(6 * sizeof(int));
    //set array values
    int *a = array;
    int *b = array + 5;
    

    (几乎)相同。

    【讨论】:

    • 好的,这是有道理的。减去两个相同类型的指针并获得它们之间的距离是否有一些逻辑或直觉?编辑:没关系我在谷歌上找到了很多答案(stackoverflow.com/questions/3238482/…
    • 嗯,是的。指针可以转换为数组中的索引。因此,如果一个指针指向第一个元素(索引为 0),而另一个指针指向距离第一个元素更远的元素大小的 4 倍(相当于数组中的第 5 个元素 - 索引为 4),那么通过提取它们你会知道,它们之间有 4 个元素(如减: 4 - 0 )。
    • 啊是不是像 *(a+i)-*(a+j) = i-j。这在直觉上是有道理的。
    • 好吧,没有这些星号 - 是的。
    【解决方案3】:

    表达式allocbuf + ALLOCSIZE - allocp 将给出指针&allocbuf[ALLOCSIZE] 和指针allocp 之间的元素数。
    allocbuf + ALLOCSIZE - allocp >= n 只检查n 是否小于指针&allocbuf[ALLOCSIZE] 之间的元素数和allocp 与否。

    注意

    C11:6.5.6 加法运算符(p9):

    当两个指针相减时,两个指针都应该指向同一个数组对象的元素,或者是数组对象最后一个元素的后一个; 结果是两个数组元素的下标之差。 [...]。
    换句话说,如果表达式PQ 分别指向数组对象的i-th 和j-th 元素,表达式(P)-(Q) 的值是@987654333 @ 前提是该值适合ptrdiff_t 类型的对象。

    【讨论】:

    • 仅在第一次运行时。如果 allocp 在 alloc 函数内增加 n,那么在下一次调用 alloc 函数时这将不准确。
    • @zoska;我不确定。片段没有解释太多。
    • @hacks 是的,但如果不是这样,allocp 就没有意义了
    【解决方案4】:

    最后,将allocbufallocp 视为数字:

    现在,我们不知道哪个号码,但假设我们知道allocp'' points to some element ofallocbuf``。

    那么,allocp - allocbufallocp 指向的元素的索引(记住,将它们视为数字 - 至少只要它们指向同一个内存对象)。

    总之,allocbuf + ALLOCSIZE - allocpALLOCSIZE - "the index of allocbuf that allocp is pointing to"。 换句话说,剩余元素的数量。

    条件然后检查是否有足够的剩余元素。

    【讨论】:

      【解决方案5】:
      allocbuf + ALLOCSIZE - allocp >= n
      

      可以扩展为

      (allocbuf + ALLOCSIZE) - allocp >= n
      

      显示正在发生的事情。

      (allocbuf + ALLOCSIZE)allocbuf 指向的任何位置之后返回内存中的指针ALLOCSIZE 元素。例如allocbuf指向第一个元素,而ALLOCSIZE为1000,则操作返回allocbuf之后的元素(指针)1000个元素(这实际上是未定义的内存;它是最后分配的元素之后的一个元素,因此如果要取消引用此指针,则会发生未定义的行为)。

      一旦推导出(allocbuf + ALLOCSIZE),一旦指针allocp被从中取出,它将返回一个类似size_t(无符号)的类型,它给出了(allocbuf + ALLOCSIZE)allocp之间的元素数量.例如,如果allocp 指向第 403 个元素,并且有人想从函数 alloc 中分配 637 个元素,它将执行以下操作:

      allocbuf + ALLOCSIZE - allocp - 获取备用元素的数量

      allocbuf + ALLOCSIZE - allocp >= n看是否大于等于n。如果是这样,它可以分配。

      【讨论】:

        【解决方案6】:

        我什至不确定是否可以在 C 中添加指针。

        减去两个指针返回它们之间的距离:它们之间的元素数(不是字节大小或其他任何值)。

        正如你所说,这个子表达式首先经过最后一个元素:

        allocbuf + ALLOCSIZE
        

        然后,通过减去allocp,它返回这个最后一个元素指针与存储在allocp中的下一个空闲位置之间的距离

        (allocbuf + ALLOCSIZE) - allocp
        

        如果这个距离优于n,则意味着allocbuf中还有至少n个元素的空间。

        【讨论】:

          猜你喜欢
          • 2012-01-01
          • 1970-01-01
          • 1970-01-01
          • 2022-11-11
          • 2020-12-13
          • 1970-01-01
          • 2012-07-07
          • 1970-01-01
          • 2018-02-05
          相关资源
          最近更新 更多