1

我写了这个小代码来测试我的理解。但不明白背后的一些事实。我正在使用 64 位小端机器。所以任何指针都是 8 个字节。这意味着

#include<stdio.h>
int main(){
    char *c = (char *)0x12345678889;
    long a = 1;
    int b = (long)(c-a);
    /* int cc = (int)(c-a); gives compiler error */
    printf("val = %x and b = %x", c-a,b);
    return 0;
}
Output
val = 45678888 and b = 45678888

假设起始地址是 100。因此char*100->89、101->88 ... 105->12 将存储在内存中,字节 106 和 107 将不使用。我的这个假设首先是正确的吗?由于 int 和 long 在 64 位机器中是 4 个字节,因此它将从 100,101,102 和 103 开始​​,并且只考虑这些字节。所以 45678889 - 1 = 45678888。我的理解正确吗?最后,当注释行给出编译器错误时,我不明白。编译器已隐式转换了上述行。但是为什么不在下面呢?

4

1 回答 1

1

首先,您不知道先验值是如何存储的,这取决于机器字节序。值可以从最低位到最高位存储,或者相反。你的从低到高。

其次,在许多 64 位机器上,int 长度为 4 字节,long 长度为 8 字节。发生的情况是您的机器计算类型为c-a,然后将其转换为带有值的值,然后静默截断它(长在 C 中静默转换为整数)。0x12345678888(char *)long0x12345678888

该评论给出了一个警告,因为c-a它是类型char *并且不能被静默地转换成一个int(它被认为是非常危险的 dans long to int)。好的,然后你明确地转换了它,但编译器警告你它也很危险。请注意,这些是警告而不是错误(它可能取决于编译器选项......)。

于 2013-09-11T16:35:19.640 回答