2016-02-12 68 views
-1

这是C.我正在学习C,这是一个幻灯片中的例子。为什么这个指针减法输出这个?

int main(int argc, char *argv[]) { 
    int a = 5, b = 10, c; 
    int *p = &a, *q = &b; 
    c = p - q; 
    printf("%d", c); 
    return 0; 
} 

当我运行它的输出是3,我不明白为什么。这似乎是因为它使用&它会减去内存地址,输出将是内存地址为-5。

+2

你能解释为什么你期望-5? –

+0

你问为什么从另一个减去一个指针而不是从另一个减去一个指针? –

回答

5

你正在减去指针的地址,而不是它们指向的地址,你会得到两个存储器地址之间的差异,不能保证是任何特定的。如果你在不同的机器或编译器上运行它,它将很可能是完全不同的值,因为ab可以分配到各种地址。例如,在我的机器上,它是1.类似的现象称为未定义的行为出于某种原因,因为您无法保证所有编译器和机器都有相同的结果。

如果您改为pq像这样c = *p - *q;您将得到-5作为c作为两组值之间的差异。此外,如果您将pq分配为int *p = a, *q = b;,那么您也会将c设置为-5,因为那样您就可以将指针设置为不同的地址,并在尝试访问之后尝试访问,在任何情况下都会是一个糟糕的主意。

+0

谢谢,但我没有试图减去他们指向的东西,这是一个来自老师的例子,我不理解它,我只是在脑海中想到它会是-5。你能解释为什么它是3吗? –

+0

@BenjaminDagg这正是我在回答中解释的内存地址的差异。它现在可能是3,但是可以在不同的计算机或编译器上重新编译它,它很可能会非常不同,因为地址会有所不同。 – Dom

+0

@BenjaminDagg没有什么特别的原因,它只是3.它碰巧是3.如果你抛硬币,它可能会出现,但没有理由出现在头上。它只是。你为什么期望-5?这就是错误 - 你没有理由期待这一点。 –

3

减去2个不是同一个数组的指针是未定义的行为。

当两个指针相减时,它们都应指向同一个数组对象的元素,或者指向数组对象的最后一个元素之后的元素;结果是两个数组元素的下标差异。 C11§6.5.69

相反,得到一些数字差异,值转换为intptr_t

int main(int argc, char *argv[]) { 
    int a = 5, b = 10, c; 
    int *p = &a, *q = &b; 
    intptr_t ip = (intptr_t) p; 
    intptr_t iq = (intptr_t) q; 
    intptr_t diff = ip -iq; 
    printf("%lld", (long long) diff); 
    return 0; 
} 

当然您打印的值可能不是5. int的位置从编译变化进行编译。