2013-10-29 122 views
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; 
} 

我明白为什么第二个printf打印0

ptr2 - ptr1 

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

+1

问下问题? –

+0

为什么你投到(int *)? – Jerry

+0

See:'(int *)ptr1 + 1 ** **(int *)ptr2' –

回答

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 

编辑:我错了,说,中投迫使指针对准

+1

我的机器上int *的sizeof是8bytes。然而ptr2 = ptr1 + 5给出1。所以我假设即使尺寸是8字节,它也可以在4字节边界上对齐。我对吗? –

+0

@IanMcGrath'sizeof(int)'是4,而不是'sizeof(int *)' –

+0

我是,错了我修复了我的答案 –

1

铸造一个char终场前int*将使其对准4字节(考虑int是4个字节在这里)。虽然ptr1ptr2是3个字节,但将它们转换为int*,结果会得到相同的地址 - 因此会导致结果。

4

如果要检查地址之间的距离,请不要使用(int *)(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,use "%td" character for ptrdiff_t

+1

不知道。有一个+1,我接受了Benoit Blanchon的回答,因为它解释了为什么它是0.仍然有用,知道你提到了什么。 –

+1

根据C11dr 6.5.6 9,不同之处在于'ptrdiff_t'类型。因此,将差异转换为'(ptrdiff_t)'类型不会改变任何内容。对于'printf()'这种类型,应该像'printf(“%td \ n”,ptr2 - ptr1)''中那样使用't'修饰符'。 – chux

+0

@chux,我不知道'%td',编辑过,谢谢 –

0

这是因为sizeof(int) == 4

每个char需要1个字节。你的字符数组看起来像这样的记忆:

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

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

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

因此必须将Ints对齐到4字节边界。您的编译器将地址别名到最低的整数边界。你会注意到,如果你使用4而不是3,这可以按照你的预期工作。因为printf不是严格键入的,即%ld格式不包含以下信息:该参数是一个int指针。

相关问题