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;
}

I understand

 ptr2 - ptr1

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

Grijesh Chauhan
  • 57,103
  • 20
  • 141
  • 208
Ian McGrath
  • 982
  • 2
  • 10
  • 23

4 Answers4

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

Benoit Blanchon
  • 13,364
  • 4
  • 73
  • 81
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.

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

Community
  • 1
  • 1
David Ranieri
  • 39,972
  • 7
  • 52
  • 94
  • 1
    Did not know that. Have a +1, I accepted Benoit Blanchon's response because it explained me why it was 0. Still useful to know what you mentioned. – Ian McGrath Oct 29 '13 at 12:14
  • 1
    Per C11dr 6.5.6 9, the difference is type `ptrdiff_t`. Thus casting the difference to type `(ptrdiff_t)` does not change anything. To `printf()` this type, one should use `t` modifier as in `printf ("%td\n", ptr2 - ptr1)`. – chux - Reinstate Monica Oct 29 '13 at 14:42
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.

Siddhartha Ghosh
  • 2,988
  • 5
  • 18
  • 25
0

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

David Ranieri
  • 39,972
  • 7
  • 52
  • 94