简体   繁体   中英

Why does second printf print 0

#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.

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

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.

#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 .

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.

This is because sizeof(int) == 4

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

[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:

[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.

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, ie the %ld format does not contain the information that the parameter is an int pointer.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM