-3
char *x = "world";
x = &x[6];  
printf("%s", x);

Hi I can't understand why the above code is outputting the first argument in the printf statement. If I change it to printf("f%s",x); it outputs "ff%s" why does it output ff twice?

Thanks

nb023
  • 35
  • 1
  • 1
  • 6

3 Answers3

4

Because you are reading beyond the array boundary. Your array is of length 6 (0-5) and you're accessing 6th member (your last available is 5th). That is an undefined operation and will do unpredictable things like print out portion of your printf statement.

rost0031
  • 1,894
  • 12
  • 21
  • I am sure that it will always print `"%s"` because that is intended, since the string literals are stored next to each other. – Iharob Al Asimi Jul 01 '15 at 23:53
  • 2
    It's an undefined operation. It doesn't HAVE to do anything. – rost0031 Jul 01 '15 at 23:54
  • 2
    It is implementation dependent as far as I know, but indeed most compilers might simply implement it the same way I guess. – Ely Jul 01 '15 at 23:55
  • I understand what undefined behavior is, but I bet you to try this with any compilation flags without changing the code, it will print `"%s"`. – Iharob Al Asimi Jul 01 '15 at 23:56
  • The point is it's not guaranteed. Someone can have a compiler that meets the spec and not behave in this manner. – rost0031 Jul 01 '15 at 23:59
  • 3
    @iharob You lose the bet, here's an example where I didn't change the function but creating another function in the same file changes the behaviour (at least with my compiler): https://gist.github.com/arkku/6c4586cc05f510ceb551 – Arkku Jul 02 '15 at 00:01
  • @Arkku I said without changing the code, you can change the string, but not the code. The program at the link is a completely different one. – Iharob Al Asimi Jul 02 '15 at 00:17
  • @iharob I didn't change the code, only the original code is executed, it's merely the presence of another function (which is never called) that breaks it. Not adding any other code cannot have been a constraint since the OP's code is not a complete program. But of course my point was merely to illustrate how fragile the construction is, I'll concede that I took liberties with the interpretation of your “bet”. =) – Arkku Jul 02 '15 at 00:22
  • My "_bet_" was if you only use the code the OP posted in the `main()` function, not adding a single line of code to it. I don't discuss the fragility of the construction, it's very fragile of course, because it depends on the memory layout of the loaded program, which depends on many many things, adding another string literal will also change the behavior and that's what **undefined behavior** means. – Iharob Al Asimi Jul 02 '15 at 00:25
  • @iharob Ok, pasting only the OP's code into `main` and compiling with icc on Linux does not print `%s` (meanwhile compiling with gcc on the same computer does print `%s`). You still lose the bet. =) – Arkku Jul 02 '15 at 00:26
  • Yes I didn't specify the compiler hence, I do lose. :), and I do know that it's compiler dependent, I don't have icc though. – Iharob Al Asimi Jul 02 '15 at 00:27
  • `Your array is of length 6 (0-5) and you're accessing 6th member (your last available is 5th).` The last available is 5th member? But you said you have 6 elements. That doesn't make sense. – this Jul 14 '15 at 00:46
3

Coincidence. It is undefined behaviour. Your are addressing a wrong memory.

&x[6] is equivalent to &(*(x+6)). I.e. you are addressing just after the string's end value which is '\0' and it seems that the string "s%" starts there.

Ely
  • 10,860
  • 4
  • 43
  • 64
1

Because the format string is stored after "world" immediately in the read only data section, so after

x = &x[6];

now x points to the format string.

That's just a coincidence, in practice it should be not possible to predict the output of that program, but it turns out there is a way to arrange the program in memory and the knowledge of that way, allows someone to write such an interesting code.

This

char *x = "";
x = &x[1];

would not cause the same behavior for example, but anything with more than 0 characters will.

Community
  • 1
  • 1
Iharob Al Asimi
  • 52,653
  • 6
  • 59
  • 97
  • Your last statement is (sometimes) incorrect, `char *x = ""; x = &x[1]` can work: http://codepad.org/zCTXXGnj – Xymostech Jul 02 '15 at 00:06
  • I don't see any proof at the link, tested the code with gcc it doesn't work. – Iharob Al Asimi Jul 02 '15 at 00:18
  • 1
    It is a good point that in certain special cases it is possible to predict the outcome of undefined behaviour, but as a reminder to the OP and any other readers, such predictions are (by definition of undefined behaviour) never applicable to all compilers and platforms, or even different versions of the same compiler. In some cases (e.g., certain kinds of signed integer overflow) the behaviour may be fairly consistent across popular compilers and platforms, so it may be tempting to occasionally rely on such things, but strictly speaking such programs are never correct (standard) C. – Arkku Jul 02 '15 at 00:45