0

In the following snippet, pointer addresses and values are referenced as the type size_t. However as the title says, the last subtraction does not make sense to me. It acts like, as if it subtracts the number multiplied with 8 instead of the actual value as seen in the int array.

#include <stdio.h>
#include <stdint.h>

int main()
{
    int i[6] = {2, 0, 1, 0, 20, 24};

    void *ptr = &i[2];

    printf("%zu\n", ((size_t*)ptr));
    printf("%zu\n", *((size_t*)ptr));
    printf("%zu\n", ((size_t*)ptr) - *((size_t*)ptr));
}
martinjlowm
  • 871
  • 5
  • 8
  • What type of specifier is `%zu`? Giving warning on my compiler: `Unknown conversion type character 'z' in format`. – haccks Sep 23 '13 at 16:24
  • @haccks It is the correct conversion specifier for `size_t`. –  Sep 23 '13 at 16:29
  • @haccks `z` is a modifier for integer formats indicating the expected type of the integer parameter is `size_t`. IMHO it is not used correctly here. (C11 7.21.6.1 7) – chux - Reinstate Monica Sep 23 '13 at 16:31
  • @Jimbo It's not a GNU extension, it's a standard specifier, present in C99 and later. –  Sep 23 '13 at 16:31
  • @chux That's exactly right, it's (ab)used for a `size_t *` whereas it would expect a `size_t`. –  Sep 23 '13 at 16:32
  • @H2CO3: thanks for letting me know, will read up on that one! Have deleted comment. – Jimbo Sep 23 '13 at 16:32
  • @H2CO3; It is giving error on **GCC 4.7.1** (C99 mode) – haccks Sep 23 '13 at 16:53

2 Answers2

3

First thing to note is that you're accessing a signed integer variable through a pointer to an unsigned integer variable. Also note that sizeof(size_t) may not necessarily equal sizeof(int)!

The line:

printf("%zu\n", ((size_t*)ptr) - *((size_t*)ptr));

Effectively Does AddressOf(i[2]) - i[2], which is AddressOf(i[2]) - 1.

In C pointer arithmetic the address is decremented not by 1, but by 1 * sizeof(data type), which is whatever sizeof(size_t) is on your machine. If you're on a 64-bit machine this could be 8 bytes. This the address you get will be -8 and not, as I think you're expecting, -1...

EDIT: The %z could probably be %p for pointer addresses. The casts to size_t * are not needed and could be dangerous as discussed above...

Jimbo
  • 4,352
  • 3
  • 27
  • 44
0

You are subtracting i[2] == 1 from a size_t pointer, so the actual difference is sizeof(size_t) == 8.

Paul Evans
  • 27,315
  • 3
  • 37
  • 54