为什么执行结束时的j为“1”? 在64位Unix计算机上使用以下标志 gcc -m32 xxx.c 进行编译。
#include <stdio.h>
int main(int argc, char **argv)
{
int *q = (int *)2;
char *r = (char *)1;
int j;
q++;
r++;
j = (int *)q - (int *)r;
printf("j = %d\n", j);
return 0;
}
代码仅用于学术目的! ;)
答案 0 :(得分:4)
首先,从理论上讲,这是所有未定义的行为,因为您使用指针未分配内存,比较不属于同一数组的内容等。
现在,把它放在一边,一旦你清楚了指针运算的机制,它就很容易了:
int *q = (int *)2;
char *r = (char *)1;
int j;
// a pointer is incremented in steps of the size of its "base type"; this
// allows to move to the next element if you are pointing inside an array
q++; // q=(int*)(2+sizeof(int))=(int *)6
r++; // r=(char *(1+sizeof(char))=(int *)2;
// again, the difference between two pointers is computed in units of the
// base type; in an array, this gives you how many places are two elements
// apart
j = (int *)q - (int *)r; // (6-2)/sizeof(int)=1
(此处sizeof(int)
为4,因为您使用gcc和-m32
进行了编译,而根据sizeof(char)
的定义,sizeof
为1
答案 1 :(得分:1)
注意:您正在调用未定义的行为,没有任何说明
int
的对齐方式为2
或更少;也不是同一个数组的q
和r
成员,也不是同一个对象..你永远不应该在你的代码片段中做你正在做的事情。
一个人不应该轻易采取未定义的行为,你的代码的结果是高度特定于实现的,并且几乎可以做任何事情。但理论上,代码将被解释如下所述,但没有这样的保证。
j
将是q
和r
之间的距离(均被解释为int*
)。
增加指向int
的指针会将sizeof(int)
个字节向前移动,而将指针递增到char
会将其sizeof(char)
字节向前移动。
从另一个指针中减去一个指针会产生它们之间的元素的数量,而不是字节数。
假设底层实现具有sizeof(int) = 4
,我们将使用以下伪代码:
int_ptr q = 2
char_ptr r = 1
/* ++q -> */ value_of(q) += 4; // sizeof(int) = 4, value_of(q) = 6
/* ++r -> */ value_of(r) += 1; // sizeof(char) = 1, value_of(r) = 2
int j = int_ptr(q) - int_ptr(r); // j = 1
// (value_of(q) - value_of(r))/sizeof(int)
答案:j = 1