3
#include<stdio.h>
int main()
{
    char arr[] = "somestring";
    char *ptr1 = arr;
    char *ptr2 = ptr1 + 3;
    printf("ptr2 - ptr1 = %ld\n", ptr2 - ptr1);
    printf("(int*)ptr2 - (int*) ptr1 = %ld",  (int*)ptr2 - (int*)ptr1);
    return 0;
}

我明白

 ptr2 - ptr1

给出 3 但无法弄清楚为什么第二个 printf 打印 0。

4

4 回答 4

8

这是因为当你减去两个指针时,你得到的指针之间的距离是元素数量,而不是字节。

(char*)ptr2-(char*)ptr1  // distance is 3*sizeof(char), ie 3
(int*)ptr2-(int*)ptr1  // distance is 0.75*sizeof(int), rounded to 0 

编辑:我说演员强制指针对齐是错误的

于 2013-10-29T12:00:25.823 回答
4

如果要检查地址之间的距离,请不要使用(int *)or (void *)ptrdiff_t是一种能够表示任何有效指针减法运算结果的类型。

#include <stdio.h>
#include <stddef.h>

int main(void)
{
    char arr[] = "somestring";
    char *ptr1 = arr;
    char *ptr2 = ptr1 + 3;
    ptrdiff_t diff = ptr2 - ptr1;

    printf ("ptr2 - ptr1 = %td\n", diff);
    return 0;
}

编辑:正如@chux 所指出的,"%td"字符用于ptrdiff_t.

于 2013-10-29T12:12:23.797 回答
1

投射一个char指针int*会使它与 4 字节对齐(这里考虑到 int 是 4 个字节)。虽然ptr1andptr2相距 3 个字节,但将它们转换为int*,会产生相同的地址——因此是结果。

于 2013-10-29T12:05:08.400 回答
0

这是因为sizeof(int) == 4

每个字符占用 1 个字节。您的字符数组在内存中如下所示:

[s][o][m][e][s][t][r][i][n][g][0]

当您有一个 int 数组时,每个 int 占用四个字节。存储 '1' 和 '2' 在概念上看起来更像这样:

[0][0][0][1][0][0][0][2]

因此,整数必须与 4 字节边界对齐。您的编译器将地址别名为最低整数边界。您会注意到,如果您使用 4 而不是 3,这将按预期工作。

您必须执行减法才能做到这一点的原因(只是将转换后的指针传递给 printf 不会这样做)是因为printf没有严格类型化,即%ld格式不包含参数是 int 指针的信息.

于 2013-10-29T12:17:22.743 回答