1

这是代码:

#include<stdio.h>
#include<conio.h>

int main()
{
    int *p1,*p2;
    int m=2,n=3;
    m=p2-p1;
    printf("\np2=%u",p2);
    printf("\np1=%u",p1);   
    printf("\nm=%d",m);       
    getch();
    return 0;
}

这给出了输出:

p2= 2686792
p1= 1993645620
m= -497739707

我对代码和输出有两个疑问:

  1. 由于 'm' 是一个 int,它不应该将 p2-p1 作为输入,因为 p1 和 p2 都是指针并且 m 是一个整数,它应该给出一个错误,例如“从 'int' 到 'int' 的无效转换”但是不是。为什么?

  2. 即使在接受输入之后,差异也是无效的。为什么?

4

2 回答 2

1

由于 'm' 是一个 int,它不应该将 p2-p1 作为输入,因为 p1 和 p2 都是指针并且 m 是一个整数,它应该给出一个错误,例如“从 'int' 到 'int' 的无效转换”但是不是。为什么?

这种类型的错误或警告取决于您使用的编译器。C 编译器经常给程序员很多绳索来吊死自己……

即使在接受输入之后,差异也是无效的。为什么?

其实区别是对的!它使用指针算法来执行计算。所以对于这个例子..

p2= 2686792

p1= 1993645620

由于指针没有被初始化,它们被分配了一些像上面那样的垃圾值。现在,您要执行 p2 - p1 操作,即您要求的内存地址恰好位于 p2 之前的 p1 内存块。由于 p1 和 p2 是指向整数的指针,因此内存块的大小为sizeof(int)(几乎总是 4 个字节)。所以:

p2 - p1 = (2686792 - 1993645620) / sizeof(int)= (2686792 - 1993645620) / 4 = -497739707

于 2013-08-07T18:50:40.840 回答
0

由于 'm' 是一个 int,它不应该将 p2-p1 作为输入,因为 p1 和 p2 都是指针并且 m 是一个整数,它应该给出一个错误,例如“从 'int' 到 'int' 的无效转换”但是不是。为什么?

C++ 规范声明这是合法的。
来自 C++11 规范 5.7.6:

当两个指向同一个数组对象的元素的指针相减时,结果就是两个数组元素的下标之差。结果的类型是实现定义的有符号整数类型;此类型应与标头 (18.2) 中定义为 std::ptrdiff_t 的类型相同。

...稍后在该段中...

除非两个指针都指向同一个数组对象的元素,或者指向数组对象的最后一个元素,否则行为是未定义的。

p2 - p1 的结果与 std::ptrdiff_t 的类型相同,但没有说明编译器不能将其定义为

namspace std {
    typedef ptrdiff_t int;
}

但是,您也无法保证这将适用于所有平台。例如,某些平台(尤其是 64 位平台)将对 ptrdiff_t 使用 long。在这些平台上,您的代码将无法编译,因为它依赖于 ptrdiff_t 的实现定义类型。

至于您的第二个问题,C++ 规范 5.7.6 中的措辞暗示了为什么它们以它们的工作方式工作。措辞表明该语言的作者希望指针算术支持快速算术,同时通过数组工作。因此,当在操作数组的上下文中使用时,定义了指针减法的结果以产生方便的结果。您可以构建一种语言,其中两个指针之间的差异是它们的内存地址(以字节为单位)之间的差异,并且您将拥有一致的工作语言。然而,一门好的语言总是能物超所值。作者认为对数组的干净操作比能够获得字节差更有价值。例如:

double* findADouble(double* begin, double* end, double valueToSearchFor)
{
    for (double* iter = begin; iter != end; iter++) {
        if (*iter == valueToSearchFor)
            return iter;
    }
    return 0;
}

必须有一个 sizeof,我们必须使用 += 而不是 ++。

double* findADouble(double* begin, double* end, double valueToSearchFor)
{
    for (double* iter = begin; iter != end; iter += sizeof(double)) {
        if (*iter == valueToSearchFor)
            return iter;
    }
    return 0;
}

在他们的决定中也值得注意:当规则是在 C 中创建时,优化编译器并不擅长他们的工作。iter += sizeof(double) 可以编译成比 ++iter 效率低得多的汇编代码,即使这两个操作基本上做同样的事情。现代优化器对此没有任何问题,但语法仍然存在。

于 2013-09-02T18:16:12.907 回答