0

Why is the last output "eU2"?

#include<stdio.h>
#include<string.h>

void main()
{
    char str1[] = "See the stone set in your eyes";
    char str2[] = "U2";
    char* ptr;
    ptr = &str1[3];//the stone...
    printf("%d\n", str1 - ptr); // -3
    ptr[-1] = 0;// del s
    ptr = (++ptr)+1;  
    printf("%s\n", ptr); // he stone set in your eyes
    strcpy(ptr, str1+1); // ee the stone set in your eyes
    strcat(ptr-2, str2); 
    printf("%s\n", ptr);
}

I wrote notes next to lines I understood

jps
  • 20,041
  • 15
  • 75
  • 79
Or_Melamed
  • 19
  • 4
  • 2
    What is the desired output? – L_R Dec 14 '22 at 13:20
  • its a question I got in my c test, you need to write what will be the output But I don't understand why the output is "eU2" – Or_Melamed Dec 14 '22 at 13:22
  • Have you tried stepping through your program with a debugger? – Refugnic Eternium Dec 14 '22 at 13:23
  • 3
    Whoever gave you this exercise is somewhat incompetent. Unfortunately this means you should suspect the accuracy of many of the lessons you've "learned". There are at least three problems: (1) It should be `int main()`. (2) The line `ptr = (++ptr)+1;` modifies `ptr` twice and so is undefined. (3) The line `strcpy(ptr, str1+1);` copies a string on top of itself and so is undefined. Problem (1) is innocuous (but poor form); problem (3) probably won't cause a problem but is considerably poor form, and problem (2) is a *real* problem. – Steve Summit Dec 14 '22 at 13:52
  • 1
    Also (4) the line `printf("%ld\n", str1 - ptr);` has a potential format mismatch, since the difference between two pointers is not necessarily type `long`. – Steve Summit Dec 14 '22 at 13:55
  • @Steve Summit If you have no error handling it doesn't get better if you return int from main(). – The incredible Jan Dec 14 '22 at 14:07
  • @TheincredibleJan That's kind of like saying, "If you have no bullets in the gun, it doesn't matter if you hold it to your head and pull the trigger." Probably innocuous, but definitely poor form. – Steve Summit Dec 14 '22 at 15:54
  • @SteveSummit Please add your comment as an answer. – Roman Podymov Dec 14 '22 at 16:43
  • @SteveSummit I have a question about ```ptr = (++ptr)+1``` being UB. I believe we can agree on the fact that the operations on the right hand side of the assignment are executed before the assignment takes place, although we don't know in what order. In this case, the operations are both increments: does it really matter that we don't know which one comes first? Isn't the result the same no matter whether ```++ptr``` or ```ptr+1``` is executed first? – picchiolu Dec 15 '22 at 06:35
  • 1
    @picchiolu *I believe we can agree...* — Actually, no, we most certainly can not agree! The key question is: given `++ptr`, when does the new value get stored back into `ptr`, and the answer is, *that* operation is *not* guaranteed to happen before the assignment implied by `=` takes place. See much, much more at the [canonical question on this topic](https://stackoverflow.com/questions/949433). – Steve Summit Dec 15 '22 at 14:39
  • @SteveSummit a-ha! Thanks to your reply I now understand my mistake in interpreting the UB. It's not that we don't know whether the ```+1``` occurs before or after the ```++ptr```: the problem is the ```ptr = (++ptr)``` part of the line! Got it. Thank you so much for taking the time to educate me! I appreciate it. – picchiolu Dec 15 '22 at 14:53
  • 1
    @picchiolu The other thing is, even if `ptr = (++ptr) + 1` weren't undefined, it's still just insane! If you want to add one to `ptr`, and then add 1 again, the way to do that is `ptr = (ptr + 1) + 1`. What was someone thining with that extra `++`? Mindbenders like this arise, I believe, because people get it into their heads that `++i` is a shortcut for `i + 1`. But it is not: it does much, much more than just computing `i`'s value, plus 1! – Steve Summit Dec 15 '22 at 15:10

1 Answers1

3

Based on Steve Summit's comments, I replaced ptr = (++ptr)+1, which leads to undefined behavior, with two repetitions of ptr++.

#include<stdio.h>
#include<string.h>

int main(void)
{
    char str1[] = "See the stone set in your eyes";
    char str2[] = "U2";
    char* ptr;
    ptr = &str1[3];// points at the space before "the stone..." 
    printf("%ld\n", str1 - ptr); // -3
    ptr[-1] = 0; // replaces the second e of see with 0 in str1
    ptr++;
    ptr++; // points to the h of "the stone..." 
    printf("%s\n", ptr); // he stone set in your eyes
    strcpy(ptr, str1+1); // ptr points to "e\0 the stone set in your eyes"
    strcat(ptr-2, str2); // concatenates the string "e\0" with "U2\0"
    printf("%s\n", ptr); // prints eU2
}
picchiolu
  • 1,120
  • 5
  • 20