【发布时间】:2010-01-22 13:35:11
【问题描述】:
鉴于此代码:
int *p, *q;
p = (int *) 1000;
q = (int *) 2000;
q - p 是什么以及如何使用?
【问题讨论】:
标签: c pointer-arithmetic
鉴于此代码:
int *p, *q;
p = (int *) 1000;
q = (int *) 2000;
q - p 是什么以及如何使用?
【问题讨论】:
标签: c pointer-arithmetic
根据标准,它实际上是未定义的。指针算法不能保证工作,除非指针都指向同一个数组中的一个元素,或者仅仅指向同一个数组之外的元素。
标准的相关部分是 6.5.6:9(c1x 的 n1362 草案,但自 c99 以来没有改变),其中规定:
当两个指针相减时,都指向同一个数组对象的元素, 或者数组对象的最后一个元素;结果是 两个数组元素的下标。
如果您的 int 数据类型是 4 个字节,您很可能会得到 250,但不能保证。未定义的行为(与实现定义的行为不同)意味着未定义。任何事情都可能发生,甚至包括大部分时空的彻底破坏。
进修课程:
【讨论】:
q - p 是 250。
2000 - 1000 = 1000
1000 / sizeof(int) = 250
指针运算,假设 sizeof(int) 为 4。
struct foo { int ar[1000]; } big[10];
char small[10];
struct foo *fs, *fe;
char *ss, *se;
fs = &big[0]; fe = &big[9];
ss = &small[0]; se = &small[9];
fe - fs == se - ss;
也就是说,本例中两个指针的区别在于它们之间的数组元素个数。在这种情况下,它是 0、1、... 8 或 9 个元素。
【讨论】:
q-p 应该返回从p 到q 应该执行的增量步数。这是1000 / sizeof(int),等于250。记住q++实际上会转到下一个int类型的元素,而不是在它的中间,所以它应该在指针的实际值上加4。结果就是这样。
【讨论】:
答案:
q-p 将是 250,假设您在一台 int 为 4 字节的机器上。
计算是:
q - p = 1000 1000 / 4(整数大小)= 250
背后的理念:
指针算法背后的想法是,如果您有一个指向 1000 的 int 指针和一个指向 2000 的 int 指针,并要求两者之间的差异,那么您就不询问 2000 是多少-1000。您要问的是,我可以在两者之间放置多少 int。
这对于各种操作都很方便,例如:
int *i = 100;
i++; // This is **not** 101, it is 104, cause you actually want the next place an int could fit in memory.
这在处理数组时特别有用。一个整数数组(定义为int arr[10])基本上被视为一个指针。当你写 arr[5] 时,编译器会将其转换为 *(arr + 5),即在名为 arr 的 int 指针上加 5,并获取该地址处的值。
之所以有效,是因为arr + 5 不是的意思是“将 arr 的值加 5”,它的意思是“在 arr 的值上加任何必要的值以前进 5 @ 987654332@s”,或者更准确地说,“将 5 * sizeof(int) 添加到 arr 的值”
【讨论】:
由于 p 指向一个 int,所以 q,q-p 将是 1000。
【讨论】:
int 和int* 之间的转换留给其他人考虑,仍然存在(int)(p+1) 等于((int)p)+sizeof(int) 的事实。同样,当您减去指针时,如在(p+1)-p 中,您会得到结果1。但是如果你在转换后减去,如((int)(p+1)) - ((int)p),你会得到sizeof(int)。