-4

I am confused with the strange output of the following c program. I am using TurboC and DevC compiler

I will be really pleased if someone will help me out in this.

Program

#include<stdio.h>
#include<conio.h>
int main()
{
    clrscr();
    printf("%d","hb");

    printf("%d","abcde"-"abcde");
    //Output is -6  why ?

    return 0;

}

Outputs For TurboC

printf("%d","hb");
//Output is 173 Why ?
// No matter what I write in place of "hb" the output is always 173

printf("%d","abcde"-"abcde");
//Output is -6  why ?

For Dev C

printf("%d","hb");
    //Output is  4210688 Why ?
    // No matter what I write in place of "hb" the output is always 4210688


printf("%d","abcde"-"abcde");
//Output is 0 why ?
prateek569
  • 73
  • 5
  • You should just write `printf("hdfetgdffgddb")`. – MoDzeus Nov 28 '15 at 22:23
  • You used the wrong type conversion "%d" instead of "%s". %d is for integers, %s for strings – Zorgatone Nov 28 '15 at 22:24
  • 6
    undefined behavior is undefined, episode 71837469. – The Paramagnetic Croissant Nov 28 '15 at 22:24
  • @schizo I know the correct syntax of printing string. I just want to know why I am getting such output. I was asked in my exam paper – prateek569 Nov 28 '15 at 22:26
  • 1
    Just write 'UB 'and move on to the next question. – Martin James Nov 28 '15 at 22:27
  • I don't get it, what's the point of this garbage question? – Blindy Nov 28 '15 at 22:27
  • 1
    @Blindy it's just another annoying 'explain UB' :( – Martin James Nov 28 '15 at 22:28
  • @Blindy I was asked this question in my Exam and I was blank – prateek569 Nov 28 '15 at 22:29
  • 1
    @prateek569, you're mistaking, the answer you accepted is wrong. The real answer is that it's all undefined behaviour (look it up), and any and all guesses you two make are at best useless and at worst (and most likely) causes for bugs. By all means, keep your "appropriate" comments, but if you worked under me I'd fire you on the spot. – Blindy Nov 29 '15 at 05:53
  • @prateek569 nobody "misguided" you – except nnn, who gave a wrong answer which you believed and accepted. Perhaps because it's more appealing for you to have a "sensible explanation" than to accept that it's undefined behavior. – The Paramagnetic Croissant Nov 29 '15 at 09:03
  • @Blindy I edited my answer, please review it, I don't want to misguide. I posted it only in the idea that the OP mentioned this as an exam question. – nnn Nov 29 '15 at 15:21
  • @TheParamagneticCroissant I edited my answer, please review it, I don't want to misguide. I posted it only in the idea that the OP mentioned this as an exam question. – nnn Nov 29 '15 at 15:22

1 Answers1

-2

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.

Community
  • 1
  • 1
nnn
  • 3,980
  • 1
  • 13
  • 17
  • @prateek569 no, in fact this is the only incorrect answer. – The Paramagnetic Croissant Nov 29 '15 at 09:03
  • "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." I have no idea where you got that from. I mean pretty much everything else is wrong too, but this is a base misunderstanding of the language itself. – Blindy Nov 29 '15 at 20:00
  • @Blindy https://gcc.gnu.org/onlinedocs/libstdc++/manual/iterators.html#iterators.predefined.end – nnn Nov 29 '15 at 20:46
  • @Blindy http://stackoverflow.com/questions/988158/take-the-address-of-a-one-past-the-end-array-element-via-subscript-legal-by-the – nnn Nov 29 '15 at 20:55
  • Neither of those support your argument. Doesn't matter, you keep thinking you're right, won't reply again. – Blindy Nov 30 '15 at 05:34
  • @Blindy _"When two pointers are subtracted, both shall point to elements of the same array object, or one past the last element of the array object; the result is the difference of the subscripts of the two array elements."_ - this is extracted from [N1256 C99 Standard draft](http://www.open-std.org/jtc1/sc22/wg14/www/docs/n1256.pdf). And I wanted to say exactly the same thing in the answer. Please reply and tell me what else is wrong. – nnn Nov 30 '15 at 09:32