C 为什么第二个printf打印0

C 为什么第二个printf打印0,c,pointers,output,C,Pointers,Output,给出了3,但无法理解为什么第二个printf打印0。这是因为当你减去两个指针时,指针之间的距离是以元素的数量表示的,而不是以字节表示的 ptr2 - ptr1 编辑:我错了,我说强制转换强制指针对齐将char指针与int*对齐将使其与4字节对齐(这里考虑int是4字节)。虽然ptr1和ptr2相距3个字节,但将它们强制转换为int*,结果是相同的地址——因此就是结果。如果要检查地址之间的距离,请不要使用(int*)或(void*),ptrdiff\u t是一种能够表示任何有效指针减法操作结果

给出了3,但无法理解为什么第二个printf打印0。

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

 ptr2 - ptr1

编辑:我错了,我说强制转换强制指针对齐

char
指针与
int*
对齐将使其与4字节对齐(这里考虑int是4字节)。虽然
ptr1
ptr2
相距3个字节,但将它们强制转换为
int*
,结果是相同的地址——因此就是结果。

如果要检查地址之间的距离,请不要使用
(int*)
(void*)
ptrdiff\u t
是一种能够表示任何有效指针减法操作结果的类型

(char*)ptr2-(char*)ptr1  // distance is 3*sizeof(char), ie 3
(int*)ptr2-(int*)ptr1  // distance is 0.75*sizeof(int), rounded to 0 
#包括
#包括
内部主(空)
{
char arr[]=“somestring”;
char*ptr1=arr;
char*ptr2=ptr1+3;
ptrdiff_t diff=ptr2-ptr1;
printf(“ptr2-ptr1=%td\n”,diff);
返回0;
}

编辑:正如@chux所指出的,.

这是因为
sizeof(int)==4

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

#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;
}
当您有一个整数数组时,每个整数占用四个字节。存储“1”和“2”在概念上更像这样:

[s][o][m][e][s][t][r][i][n][g][0]
因此,整数必须与4字节边界对齐。编译器正在将地址别名设置为最低整数边界。您会注意到,如果您使用4而不是3,这将按照您的预期工作


您必须执行减法以使其执行减法操作(仅将强制转换的指针传递给printf不会执行此操作)的原因是
printf
不是严格键入的,即
%ld
格式不包含参数是int指针的信息。

询问问题时投反对票?@Jerry,我没有。这是我参加的一个C测试。我弄错了。当你添加
1
时,尝试调试并根据指针数学检查@lan的值(监视),然后结果将指向相同类型的下一个位置,假设
arr==12
,然后
ptr1==12
,然后
ptr1+3
=
15
,然后
ptr2==15
。现在
ptr1
=
12
如果您在添加
+
之前对
int*
进行分类,那么
(int*)ptr1+1
=
16
对于
sizeof(int*)==4
的系统,这是未定义的行为(UB)?取消引用
(int*)ptr1
,因为它没有正确对齐(取决于平台)。但也许减法本身就是UB,指针对齐不正确?在我的机器上,int*的大小是8字节。然而,ptr2=ptr1+5给出1。所以我假设即使大小是8字节,它也可以在4字节边界上对齐。我说得对吗?@IanMcGrath
sizeof(int)
是4,而不是
sizeof(int*)
@BenoitBlanchon,现在它有了完美的意义。谢谢。对不起,我走得太快了。我不知道。如果a+1,我接受了Benoit Blanchon的回答,因为它解释了为什么是0。了解您提到的内容仍然很有用。根据C11dr 6.5.6 9,区别在于类型
ptrdiff\u t
。因此,将差异转换为type
(ptrdiff\u t)
不会改变任何内容。要
printf()
此类型,应使用
t
修饰符,如
printf(“%td\n”,ptr2-ptr1)
中所述。
[s][o][m][e][s][t][r][i][n][g][0]
[0][0][0][1][0][0][0][2]