Thread: Why does this work?

  1. #1
    C lover
    Join Date
    Oct 2007
    Location
    Virginia
    Posts
    266

    Why does this work?

    Code:
    #include <stdio.h>
    
    int main(int argc, char ** argv) {
    
        printf("hello!!!"+printf("world"));
        return 0;
    
    }
    The output is

    Code:
    world!!!
    EDIT: I believe it's got something to do with both locations sharing some of the memory... The arg to printf is just a "const char *" and it gets offset by the return from the second printf.
    Last edited by Syscal; 10-08-2013 at 05:54 PM.

  2. #2
    Registered User
    Join Date
    Nov 2010
    Location
    Long Beach, CA
    Posts
    5,909
    EDIT: oogabooga's explanation is so much clearer

    Nope, not a race condition. While this does not exhibit undefined behavior like ++i + i++ would, it comes close to the "stupid code you shouldn't bother understanding since nobody does this crap in the real world" line.

    That being said, there are a few things you must understand here:

    First, printf takes a pointer to const char. It could be lots of things, for example, the start of a string literal or somewhere in the middle of a string literal.

    Second, read the docs for printf: printf(3): formatted output conversion - Linux man page. It returns the number of characters printed. Thus printf("world") returns 5 since "world" has 5 letters (it omits the null terminator).

    Lastly, realize that adding an int n (like 5) to a pointer is like incrementing that pointer n times. It's also similar to indexing an array, except that you get a pointer back instead of the element pointed to/indexed. Taking your example, say the string literal "hello!!!" had address 0x1000. Doing "hello!!!"+printf("world") is equivalent to "hello!!!" + 5 = 0x1000 + 5 = 0x1005. Since the literal is stored in adjacent bytes in memory, you basically skip the first 5 letters ("hello") and print the remaining ones, "!!!".

    So first, you must call printf("world") to know what it returns. Then, you add it to "hello!!!", and printf uses the result as the address to print to. That's why it prints "world" followed by "!!!".

    Note that this is a dangerous thing to do, since it's easy to screw up and access invalid memory (what if you changed world to "something longer" -- then you are printing past the end of "hello!!!", accessing memory you don't own and ending up with undefined behavior). In fact, if you crank up warnings on your compiler, you may see something like:
    Code:
    $ make bar
    gcc -Wall -ggdb3 -std=c99 -O0 -o bar bar.c -lm -lpthread -lrt
    bar.c: In function ‘main’:
    bar.c:5:3: warning: format not a string literal and no format arguments [-Wformat-security]

  3. #3
    - - - - - - - - oogabooga's Avatar
    Join Date
    Jan 2008
    Posts
    2,808
    Your explanation is incorrect. (EDIT: "your" here refers to syscal !)

    The inner printf is executed first, printing "world".

    printf has an int return value, which returns the number of characters printed. In this case, it returns 5.

    A string constant evaluates to the address of the first character in the string. The addition adds 5 to the address of the 'h' in "hello!!!". That makes the address point to the first exclamation mark.

    So the outer printf prints the exclamation points.
    The cost of software maintenance increases with the square of the programmer's creativity. - Robert D. Bliss

  4. #4
    C lover
    Join Date
    Oct 2007
    Location
    Virginia
    Posts
    266
    Yup, I figured as much which is why I went back and edited the post. Too slow and you beat me to the punch though. Had to really sit there and think about that before I realized what was happening. Thanks for confirming! Lots of quirks and odd things can be done with this language!

  5. #5
    Hurry Slowly vart's Avatar
    Join Date
    Oct 2006
    Location
    Rishon LeZion, Israel
    Posts
    6,788
    Quote Originally Posted by Syscal View Post
    Lots of quirks and odd things can be done with this language!
    It does not mean they should be done
    All problems in computer science can be solved by another level of indirection,
    except for the problem of too many layers of indirection.
    – David J. Wheeler

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. Would... This work?
    By HelpLol in forum C++ Programming
    Replies: 7
    Last Post: 02-11-2008, 04:43 AM
  2. How does it work?
    By ronenk in forum C Programming
    Replies: 5
    Last Post: 08-16-2004, 09:07 AM
  3. Why it does not work
    By dv007 in forum C++ Programming
    Replies: 5
    Last Post: 08-10-2002, 04:51 PM
  4. my function doesn't work! it should work
    By Unregistered in forum C Programming
    Replies: 13
    Last Post: 05-02-2002, 02:53 PM