1

I get that %d is the format specifier for type decimal, and %f is for float, but I'm not sure why the output of the 2nd print statement is 3.

#include <stdio.h>

int main()
{
    float arr[5] = {12.5, 10.0, 13.5, 90.5, 0.5};
    float *ptr1 = &arr[0];
    float *ptr2 = ptr1 + 3;
 
    printf("%f ", *ptr2);
    printf("%d", ptr2 - ptr1);
 
   return 0;
}
OkCloudy
  • 11
  • 2
  • 5
    ptr2 = ptr1 + 3; – Avi Berger Sep 13 '22 at 03:37
  • 2
    I would encourage you to consider using the `%p` format specifier for pointers: https://stackoverflow.com/a/9053835/421195. To answer your question: the value of "ptr2 - ptr1" is simply "3" :) – paulsm4 Sep 13 '22 at 03:48
  • 3
    But the correct modifier for `ptrdiff_t` (which is the result of subtracting two pointers) is `t` — as in `%td` to print the difference between two pointers as a decimal integer. – Jonathan Leffler Sep 13 '22 at 03:50
  • 1
    @paulsm4 appreciate the advice :). I was doing a geeksforgeeks quiz and was a bit confused by this. I think I'm not understanding pointers. I get that abstractly "ptr2 - ptr1" is 3 because that's how many indexes are between the two, but in my head I am saying "The address that ptr2 points to - the address that ptr1 points to" and when I think of it like that I'm not really sure how I would come up with 3. – OkCloudy Sep 13 '22 at 03:55
  • 3
    Pointer arithmetic in C is scaled by the size of the object pointed at. Adding `3` to a `float *` adds `3 * sizeof(float)` to the byte address. To see the difference, consider using `printf("%td\n", (char *)ptr2 - (char *) ptr1)` as well — the answer should be `12`. You could also use `printf("ptr1 = %p\nptr2 = %p\n", (void *)ptr1, (void *)ptr2);` to see the byte addresses. – Jonathan Leffler Sep 13 '22 at 03:58
  • @JonathanLeffler Ok now I'm starting to understand. Those print statements you provided really helped. Although now I have a question about those pointer castings you did. What is the purpose of (char *) and (void *)? How does casting a float to a char pointer give you bytes? Also when I tried printing just "(char *)ptr2" I got a really wacky number. – OkCloudy Sep 13 '22 at 04:08
  • 1
    `ptr1` is a `float *` — a pointer to a `float`. Converting the type to `char *` is a no-op on most modern machines (but was not a no-op on the machine where I learned to program C!); it simply tells the compiler to treat the address as a `char *`, so that the size of what the cast address points to is `1` (aka `sizeof(char)`). The `%p` format specifier formats the address for a `void *`, so the casts there ensure that the type passed to `printf()` is of the correct type. – Jonathan Leffler Sep 13 '22 at 04:15
  • 1
    Also, %f is double not float. – Allan Wind Sep 13 '22 at 05:23
  • "%d is the format specifier for type decimal, " --> No. `"%d"` matches type `int` to print as decimal text. For pointer subtraction the resultant type is `ptrdiff_t` which matches `"%td"`, – chux - Reinstate Monica Sep 13 '22 at 06:01
  • 2
    @OkCloudy - if this doesn't explain why you should stay well away from geeksforgeek, nothing will. Avoid so-called programming sites. Many are just plain wrong and contain horrible coding practices. Stack Overflow provides [The Definitive C Book Guide and List](https://stackoverflow.com/q/562303/3422102) to help facilitate just this type of learning. Well worth picking up a proper reference. – David C. Rankin Sep 13 '22 at 06:11

1 Answers1

2

So, you seem to have pointer arithmetic mostly down, since you understand why *ptr2 equals 90.5, but you're missing a piece here. You have to remember that ptr1 and ptr2 on their own refer to memory addresses - which are integers - and not the floating point numbers stored at those addresses. The difference of addresses ptr2 and ptr1 is 3, as you set in the line float *ptr2 = ptr1 + 3.


I can't tell exactly what your goal is here, but if you are trying to print an integer of the difference of the floats stored at those addresses (which I think you are), you'll need to dereference the pointers and perform a type cast. The final line before return 0 should be printf("%d", (int)(*ptr2 - *ptr1)). This prints 78 to the console.

But, that's only if the "assignment" here is to specifically use an integer. Realistically, it would be written more like printf("%0.f", *ptr2 - *ptr1), which keeps the number as a float but will not print anything after the decimal point.

hryrbn
  • 303
  • 3
  • 11