c - 指向数组第一个元素之前的指针

标签 c language-lawyer pointer-arithmetic

用C表示,当指针指向同一数组或指向数组末尾的一个元素时,算术和比较的定义就很好。那么在数组第一个元素之前的那个呢?只要不取消引用就可以吗?

给定

int a[10], *p;
p = a;

(1)编写--p是否合法?

(2)在表达式中写入p-1是否合法?

(3)如果(2)没问题,我可以断言p-1 < a吗?

对此存在一些实际问题。考虑一个reverse()函数,该函数可以反转以'\0'结尾的C字符串。

#include <stdio.h>

void reverse(char *p)
{
    char *b, t;

    b = p;
    while (*p != '\0')
        p++;
    if (p == b)      /* Do I really need */
        return;      /* these two lines? */
    for (p--; b < p; b++, p--)
        t = *b, *b = *p, *p = t;
}

int main(void)
{
    char a[] = "Hello";

    reverse(a);
    printf("%s\n", a);
    return 0;
}

我真的需要在代码中进行检查吗?

请从语言律师/实践角度分享您的想法,以及如何应对这种情况。

最佳答案

(1) Is it legal to write --p?



正如C语法所允许的那样,它是“合法的”,但它会调用未定义的行为。为了找到标准中的相关部分,--p等效于p = p - 1(除了p仅被评估一次)。然后:

C17 6.5.6/8

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.



评估调用未定义的行为,这意味着是否取消引用指针都没有关系-您已经调用了未定义的行为。

此外:

C17 6.5.6/9:

When two pointers are subtracted, both shall point to elements of the same array object, or one past the last element of the array object;



如果您的代码违反了ISO标准中的“必须”,它将调用未定义的行为。

(2) Is it legal to write p-1 in an expression?



与(1)相同,未定义行为。

关于如何在实践中引起问题的示例:假设将数组放置在有效内存页的最开始。当您在该页面之外递减时,可能会有硬件异常或指针陷阱表示。对于微 Controller 来说,这并不是完全不可能的情况,特别是当它们使用分段存储器映射时。

关于c - 指向数组第一个元素之前的指针,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/60163677/

相关文章:

c - 哈希表实现

c - Pascal 到 C 的翻译

c - 应该返回 -1 的 sprintf 编码错误是什么?

c - C中的指针运算

c - 如何使用指针算术循环分配的内存 C

c - 如何定义 &array 的算术

c - 需要帮助理解二叉搜索树中的父节点

c - 只有一个线程使用 memory_order_seq_cst 有用吗?

c - strncpy(d, s, 0) 带过去指针

c - 您必须为新操作系统构建新编译器吗?