c和数组边界中的指针算术

jai*_*led 6 c pointers

我浏览了一个有一些常见问题解答的网页,我发现了这个陈述.

类似地,如果a有10个元素并且ip指向a [3],则无法计算或访问ip + 10或ip - 5.(有一种特殊情况:在这种情况下,您可以计算,但不能访问,指向不在数组末尾的不存在元素的指针,在本例中是&a [10].

我对这句话感到困惑

你无法计算ip + 10

我可以理解访问元素超出界限是未定义的,但计算!!!

我编写了以下代码片段,用于计算(让我知道这是网站对计算的意义)指针越界.

#include <stdio.h>                                                                                                                                                                  

int main()                                                                                                                                                                          
{                                                                                                                                                                                   
        int a[10], i;                                                                                                                                                               
        int *p;                                                                                                                                                                     

        for (i = 0; i<10; i++)                                                                                                                                                      
                a[i] = i;                                                                                                                                                           

        p = &a[3];                                                                                                                                                                  

        printf("p = %p and p+10 = %p\n", p, p+10);                                                                                                                                  
        return 0;                                                                                                                                                                   
}                     

$ ./a.out                                                                                                                                     
p = 0xbfa53bbc and p+10 = 0xbfa53be4     
Run Code Online (Sandbox Code Playgroud)

我们可以看到p + 10指向超过p的10个元素(40个字节).那么该声明在网页中的确切含义是什么.我错误地解释了什么.

即使在K&R(A.7.7)中,该声明也是如此:

+运算符的结果是操作数的总和.可以添加指向数组中的对象的指针和任何整数类型的值.... sum是与原始指针相同类型的指针,指向同一数组中的另一个对象,与原始对象相适应.因此,如果P是指向数组中对象的指针,则表达式P + 1是指向数组中下一个对象的指针.如果sum指针指向数组边界之外,除了高端之外的第一个位置,结果是未定义的.

什么是"未定义"的意思.这是否意味着总和将是未定义的,或者它仅仅意味着当我们取消引用它时行为是未定义的.即使我们不取消引用它,只是计算指向元素越界的指针,操作是否未定义.

Ada*_*eld 9

未定义的行为意味着:绝对可能发生任何事情.它可以默默地成功,它可能会无声地失败,它可能会崩溃您的程序,它可能会蓝屏您的操作系统,或者它可能会擦除您的硬盘驱动器.其中一些不太可能,但就C语言标准而言,所有这些都是允许的行为.

在这种特殊情况下,是的,C标准说甚至在有效数组边界之外计算指针的地址而不解除引用它是未定义的行为.它说这是因为有一些神秘的系统,这样的计算可能会导致某种类型的错误.例如,您可能在可寻址内存的最末端有一个数组,并且构造一个超出该指针的指针会导致特殊地址寄存器溢出,从而产生陷阱或故障.C标准希望允许这种行为以便尽可能地便携.

但实际上,您会发现构建这样一个无效地址而不解除引用它在绝大多数系统中都有明确定义的行为,这些行为在常见用法中会遇到.除非您尝试取消引用它,否则创建无效的内存地址将不会产生任何不良影响.但是,当然,最好避免创建那些无效的地址,这样即使在那些神秘的系统上,您的代码也能完美运行.