Here, you are passing the memory address of a string literal (a char*
):
printf("%d","hb");
However, the specifier which should be used is %p
(standing for pointer):
printf("%p\n", "hb"); // The output is in hexadecimal
This will ensure that the same representation size is used by printf
when displaying it as for when it was passed to printf
. Using %d
(int
specifier) will result in undefined behaviour when sizeof(int)
is not the same as sizeof(char*)
, and even if the sizes would be equal, using %d
may result in having negative values printed (if the most significant bit is set - the sign bit of an int
).
As for any memory address, you can't expect it to be the same after the program was recompiled, and even less when using different toolchains.
When the output was the same after changing the "hb"
literal with another one, it means that it was allocated at the same address.
Here, two pointers to string literals are subtracted:
printf("%d","abcde"-"abcde");
The result of subtracting two pointers is the number of elements of that type between the addresses pointed by them. But please note, the behaviour is only defined when the pointers point to elements from the same array, or to the first element just after the end of the array.
Again, %d
may not be the right specifier to be used. An integer type with its size at least equal to the pointer type may be used, maybe long long int
(this should be checked against the specific platform). A subtraction overflow may still happen, or the result may not fit into the cast type, and then the behaviour is again undefined.
char *p1, *p2; // These should be initialized and NOT point to different arrays
printf("%lld\n", (long long int)(p1 - p2));
Also note, C standard library provides stddef.h
, which defines the ptrdiff_t
type used to store a pointer difference. See this: C: Which character should be used for ptrdiff_t in printf?
Note: As there are two different char
arrays, the pointer subtraction is undefined, and therefore information below is only based on assumptions, and presented only because the OP mentioned that this was an exam question.
In our case, as sizeof(char)
is 1, it represents exactly the difference in bytes. The difference of -6
is telling that the two identical literals "abcde"
were placed in memory first next to the second. The literal is including the string terminator, so it's size is 6.
The other thing that can be deduced from here is that the compiler used by DevC++ was "smarter" (or had other optimization options passed to), to create a single copy in the memory for the "abcde"
literal, hence the difference of 0
.
A string literal is usually placed in the read-only memory, and the program should not try to modify it, so if the compiler (or the linker in some cases) can "detect" a duplicate, it may reuse the previous literal instead.