在 K&R(C 编程语言第二版)第 5 章中,我读到了以下内容:
首先,在某些情况下可以比较指针。
如果p
and q
指向同一个数组的成员,那么关系如下==
, !=
, <
, >=
等工作正常。
这似乎意味着只能比较指向同一数组的指针。
但是当我尝试这段代码时
char t = 't';
char *pt = &t;
char x = 'x';
char *px = &x;
printf("%d\n", pt > px);
1
被打印到屏幕上。
首先,我认为我会得到未定义或某种类型或错误,因为pt
and px
不指向同一个数组(至少在我看来)。
Also is pt > px
因为两个指针都指向存储在栈上的变量,而栈是向下增长的,所以t
大于x
?这就是为什么pt > px
是真的?
当引入 malloc 时,我会更加困惑。在第 8.7 章的 K&R 中,还写了以下内容:
然而,仍然有一个假设,即指向由sbrk
可以进行有意义的比较。标准不保证这一点,该标准仅允许在数组内进行指针比较。因此这个版本的malloc
仅在一般指针比较有意义的机器之间可移植。
将指向堆上分配的空间的指针与指向堆栈变量的指针进行比较没有任何问题。
例如,以下代码运行良好,使用1
正在打印:
char t = 't';
char *pt = &t;
char *px = malloc(10);
strcpy(px, pt);
printf("%d\n", pt > px);
根据我对编译器的实验,我认为任何指针都可以与任何其他指针进行比较,无论它们单独指向哪里。此外,我认为两个指针之间的指针算术很好,无论它们分别指向哪里,因为算术只是使用指针存储的内存地址。
尽管如此,我对在 K&R 上读到的内容感到困惑。
我问的原因是因为我的教授。实际上把它变成了一个考试题。他给出了以下代码:
struct A {
char *p0;
char *p1;
};
int main(int argc, char **argv) {
char a = 0;
char *b = "W";
char c[] = [ 'L', 'O', 'L', 0 ];
struct A p[3];
p[0].p0 = &a;
p[1].p0 = b;
p[2].p0 = c;
for(int i = 0; i < 3; i++) {
p[i].p1 = malloc(10);
strcpy(p[i].p1, p[i].p0);
}
}
这些评估的目的是什么:
p[0].p0 < p[0].p1
p[1].p0 < p[1].p1
p[2].p0 < p[2].p1
答案是0
, 1
, and 0
.
(我的教授确实在考试中包含了免责声明,即问题适用于 Ubuntu Linux 16.04、64 位版本编程环境)
(编者注:如果允许更多标签,最后一部分将保证x86-64 /questions/tagged/x86-64, linux /questions/tagged/linux, 有可能assembly /questions/tagged/assembly。如果问题/类的重点是特定的低级操作系统实现细节,而不是可移植的 C。)