为什么第二个printf会打印0

时间:2021-11-13 04:04:11
#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;
}

I understand

我理解

 ptr2 - ptr1

gives 3 but cannot figure out why second printf prints 0.

给出3,但无法找出为什么第二个printf输出为0。

4 个解决方案

#1


8  

It's because when you substract two pointers, you get the distance between the pointer in number of elements, not in bytes.

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

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

EDIT: I was wrong by saying that the cast forces the pointer to be aligned

编辑:我说施放强制指针对齐是错误的

#2


4  

If you want to check the distance between addresses don't use (int *) or (void *), ptrdiff_t is a type able to represent the result of any valid pointer subtraction operation.

如果您想检查地址之间的距离不使用(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;
}

EDIT: As pointed out by @chux, use "%td" character for ptrdiff_t.

编辑:如@chux所指出,使用“%td”字符作为ptrdiff_t。

#3


1  

Casting a char pointer with int* would make it aligned to the 4bytes (considering int is 4 bytes here). Though ptr1 and ptr2 are 3 bytes away, casting them to int*, results in the same address -- hence the result.

使用int*转换字符指针将使其对齐到4bytes(这里考虑到int是4个字节)。虽然ptr1和ptr2相距3个字节,但将它们转换为int*,结果是相同的地址——因此得到了结果。

#4


0  

This is because sizeof(int) == 4

这是因为sizeof(int) = 4

Each char takes 1 byte. Your array of chars looks like this in memory:

每个字符占用一个字节。你的chars数组在内存中是这样的:

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

When you have an array of ints, each int occupies four bytes. storing '1' and '2' conceptually looks more like this:

当您有一个ints数组时,每个int都占用4个字节。存储“1”和“2”的概念看起来更像这样:

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

Ints must therefore be aligned to 4-byte boundaries. Your compiler is aliasing the address to the lowest integer boundary. You'll note that if you use 4 instead of 3 this works as you expected.

因此,Ints必须对齐到4字节的边界。你的编译器将地址混叠到最低的整数边界。您将注意到,如果您使用4而不是3,那么它就会像您预期的那样工作。

The reason you have to perform a subtraction to get it to do it (just passing the casted pointers to printf doesn't do it) is because printf is not strictly typed, i.e. the %ld format does not contain the information that the parameter is an int pointer.

您必须执行减法才能实现它(只是将已转换的指针传递给printf而不这样做)的原因是printf不是严格的类型化的,即%ld格式不包含参数是int指针的信息。

#1


8  

It's because when you substract two pointers, you get the distance between the pointer in number of elements, not in bytes.

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

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

EDIT: I was wrong by saying that the cast forces the pointer to be aligned

编辑:我说施放强制指针对齐是错误的

#2


4  

If you want to check the distance between addresses don't use (int *) or (void *), ptrdiff_t is a type able to represent the result of any valid pointer subtraction operation.

如果您想检查地址之间的距离不使用(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;
}

EDIT: As pointed out by @chux, use "%td" character for ptrdiff_t.

编辑:如@chux所指出,使用“%td”字符作为ptrdiff_t。

#3


1  

Casting a char pointer with int* would make it aligned to the 4bytes (considering int is 4 bytes here). Though ptr1 and ptr2 are 3 bytes away, casting them to int*, results in the same address -- hence the result.

使用int*转换字符指针将使其对齐到4bytes(这里考虑到int是4个字节)。虽然ptr1和ptr2相距3个字节,但将它们转换为int*,结果是相同的地址——因此得到了结果。

#4


0  

This is because sizeof(int) == 4

这是因为sizeof(int) = 4

Each char takes 1 byte. Your array of chars looks like this in memory:

每个字符占用一个字节。你的chars数组在内存中是这样的:

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

When you have an array of ints, each int occupies four bytes. storing '1' and '2' conceptually looks more like this:

当您有一个ints数组时,每个int都占用4个字节。存储“1”和“2”的概念看起来更像这样:

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

Ints must therefore be aligned to 4-byte boundaries. Your compiler is aliasing the address to the lowest integer boundary. You'll note that if you use 4 instead of 3 this works as you expected.

因此,Ints必须对齐到4字节的边界。你的编译器将地址混叠到最低的整数边界。您将注意到,如果您使用4而不是3,那么它就会像您预期的那样工作。

The reason you have to perform a subtraction to get it to do it (just passing the casted pointers to printf doesn't do it) is because printf is not strictly typed, i.e. the %ld format does not contain the information that the parameter is an int pointer.

您必须执行减法才能实现它(只是将已转换的指针传递给printf而不这样做)的原因是printf不是严格的类型化的,即%ld格式不包含参数是int指针的信息。