obfuscated

Discussion in 'C Programming' started by aarklon@gmail.com, Oct 10, 2006.

  1. Guest

    Hi all,

    can anybody please explain why this code

    main(_) {for(--_;putchar(_++["J!Mpwf!Zpv\1"]-1););}

    is producing the output:: I love you


    1) what is this under score stuff inside main parenthesis?
    2) what does this --_ mean in the initialization condition of for
    loop
    3) what is the role of this operator _ (unary minus i presume) in
    putchar
     
    , Oct 10, 2006
    #1
    1. Advertising

  2. Mike Wahler Guest

    <> wrote in message
    news:...
    > Hi all,
    >
    > can anybody please explain why this code
    >
    > main(_) {for(--_;putchar(_++["J!Mpwf!Zpv\1"]-1););}
    >
    > is producing the output:: I love you


    Not without seeing all of it.

    >
    >
    > 1) what is this under score stuff inside main parenthesis?
    > 2) what does this --_ mean in the initialization condition of for
    > loop
    > 3) what is the role of this operator _ (unary minus i presume) in
    > putchar


    No, it's not an operator at all. It's probably a macro whose
    definition you're not showing us.

    -Mike
     
    Mike Wahler, Oct 10, 2006
    #2
    1. Advertising

  3. wrote:
    > Hi all,
    >
    > can anybody please explain why this code
    >
    > main(_) {for(--_;putchar(_++["J!Mpwf!Zpv\1"]-1););}
    >
    > is producing the output:: I love you
    >
    >

    I'll bite. I might be wrong, but I'll bite.

    > 1) what is this under score stuff inside main parenthesis?

    It is an illegal (I presume) reference to something like argc. It is
    similar to "main(int _)", but very non-standard.

    I expect for those compilers that accept this will set "_" to 1 before
    we visit the for loop.

    > 2) what does this --_ mean in the initialization condition of for
    > loop

    It predecrements the C identifier "_".

    > 3) what is the role of this operator _ (unary minus i presume) in
    > putchar

    It is not an operator. It is equivalent in ways that count (standard or
    not) to "int _".

    So, we loop through the char array, getting the _th item in the array,
    subtracting 1 and printing the char we get. I suppose this presumes
    ASCII collation.
     
    Clever Monkey, Oct 10, 2006
    #3
  4. wrote:
    > Hi all,
    >
    > can anybody please explain why this code
    >
    > main(_) {for(--_;putchar(_++["J!Mpwf!Zpv\1"]-1););}
    >
    > is producing the output:: I love you



    easy. Underscore is an allowed character in an identifier. main(_)
    declares it as a parameter in place of argc. argc is 1, so if yo
    decrement it, it starts out at zero.
    That "J!... " string is just "I love you" with 1 added to each
    character.


    >
    >
    > 1) what is this under score stuff inside main parenthesis?
    > 2) what does this --_ mean in the initialization condition of for
    > loop
    > 3) what is the role of this operator _ (unary minus i presume) in
    > putchar
     
    Ancient_Hacker, Oct 10, 2006
    #4
  5. Chris Dollin Guest

    Mike Wahler wrote:

    > <> wrote in message
    > news:...
    >> Hi all,
    >>
    >> can anybody please explain why this code
    >>
    >> main(_) {for(--_;putchar(_++["J!Mpwf!Zpv\1"]-1););}
    >>
    >> is producing the output:: I love you

    >
    > Not without seeing all of it.


    That /is/ all of it.

    >> 1) what is this under score stuff inside main parenthesis?
    >> 2) what does this --_ mean in the initialization condition of for
    >> loop
    >> 3) what is the role of this operator _ (unary minus i presume) in
    >> putchar

    >
    > No, it's not an operator at all. It's probably a macro whose
    > definition you're not showing us.


    It's the first (and only) argument to `main`. The program has to
    be run with no arguments (each argument will ignore another
    leading output character, that is if the undefined behaviour [1]
    doesn't lead to metapsychic meltdown or penguins at Southend).

    It's a bit obvious, really. If it weren't for Yet More Undefined
    Behaviour, `_++["J!Mpwf!Zpv\1"]+_` would be better [2], with
    appropriate adjustments to the string.

    [1] I assume undefined behaviour because `main` wasn't declared in
    one of the Two Allowed Ways. And of course it relies on ascii
    character codes.

    [2] For values of `better` that are ... um ... er ...

    --
    Chris "Essen -9 and counting" Dollin
    Nit-picking is best done among friends.
     
    Chris Dollin, Oct 10, 2006
    #5
  6. Clever Monkey wrote:
    > wrote:
    >> Hi all,
    >>
    >> can anybody please explain why this code
    >>
    >> main(_) {for(--_;putchar(_++["J!Mpwf!Zpv\1"]-1););}
    >>
    >> is producing the output:: I love you
    >>
    >>

    > I'll bite. I might be wrong, but I'll bite.
    >
    >> 1) what is this under score stuff inside main parenthesis?

    > It is an illegal (I presume) reference to something like argc. It is
    > similar to "main(int _)", but very non-standard.
    >
    > I expect for those compilers that accept this will set "_" to 1 before
    > we visit the for loop.
    >

    (Depending on how this code is run, of course. Try running the
    executable with arguments and see what happens...)
     
    Clever Monkey, Oct 10, 2006
    #6
  7. Cong Wang Guest

    wrote:
    > Hi all,
    >
    > can anybody please explain why this code
    >
    > main(_) {for(--_;putchar(_++["J!Mpwf!Zpv\1"]-1););}
    >
    > is producing the output:: I love you
    >
    >
    > 1) what is this under score stuff inside main parenthesis?
    > 2) what does this --_ mean in the initialization condition of for
    > loop
    > 3) what is the role of this operator _ (unary minus i presume) in
    > putchar


    '_' is an argument of main, which is int; '--_' means decrease '_'
    first.

    The argument of putchar() can be rewritten as

    ("J!Mpwf!Zpv\1"[_++] )-1

    , which is a char in the string "J!Mpwf!Zpv\1".
     
    Cong Wang, Oct 10, 2006
    #7
  8. <> wrote in message
    news:...
    > Hi all,
    >
    > can anybody please explain why this code
    >
    > main(_) {for(--_;putchar(_++["J!Mpwf!Zpv\1"]-1););}
    >
    > is producing the output:: I love you
    >
    >
    > 1) what is this under score stuff inside main parenthesis?
    > 2) what does this --_ mean in the initialization condition of for
    > loop
    > 3) what is the role of this operator _ (unary minus i presume) in
    > putchar
    >


    All right, let's start:
    the '_' identifier is used instead of the more well known argc.
    Also, the a[1]=1[a] idiom is used.
    So, let's
    change the program to a more readable version:

    main(int argc) {
    for(
    --argc;
    putchar( "J!Mpwf!Zpv\1"[argc++] -1);
    ) ;
    }

    well, not much more readable, but now we can understand it:
    argc has the value 1 when the program starts, so, when the
    for starts, argc will be 0.

    Now, while the putchar("...") does not return 0, the loop
    will be executed each time and the value of argc will be
    increased. And, considering that : J-1 = I, !-1=' '(space),
    M-1 = L etc you see how I Love you is printed.

    Last point: Why does the loop stop ? Because '\1' - 0 =0,
    so, putchar will return 0 and the loop will exit :)

    Serafeim Papastefanos
     
    Papastefanos Serafeim, Oct 10, 2006
    #8
  9. Guest

    Mike Wahler wrote:

    > <> wrote in message
    > news:...
    > > Hi all,
    > >
    > > can anybody please explain why this code
    > >
    > > main(_) {for(--_;putchar(_++["J!Mpwf!Zpv\1"]-1););}
    > >
    > > is producing the output:: I love you

    >
    > Not without seeing all of it.
    >
    > >
    > >
    > > 1) what is this under score stuff inside main parenthesis?
    > > 2) what does this --_ mean in the initialization condition of for
    > > loop
    > > 3) what is the role of this operator _ (unary minus i presume) in
    > > putchar

    >
    > No, it's not an operator at all. It's probably a macro whose
    > definition you're not showing us.
    >
    > -Mike


    i am not hiding any macro definition
    i actually got this question from my friend which was as follows::

    The following code prints "I LOVE YOU".

    main(_){for(--_;putchar(_++["J!Mpwf!Zpv\1"]-1););}

    Avoid the use of digit 1 in above code to print the same output.
    Keep in mind not to use direct output text in the code :)
     
    , Oct 10, 2006
    #9
  10. jmcgill Guest

    Mike Wahler wrote:
    > <> wrote in message
    > news:...
    >> Hi all,
    >>
    >> can anybody please explain why this code
    >>
    >> main(_) {for(--_;putchar(_++["J!Mpwf!Zpv\1"]-1););}
    >>
    >> is producing the output:: I love you

    >
    > Not without seeing all of it.


    That's all of it. It's not all that strange.
    The mapping of the data to the output is obvious.

    _ gets the argc value. It gets decremented. It then is used as an
    array index (because n[a] is equivalent to a[n]), and each element of
    the array is decremented by one. When it gets to '\0', putchar returns
    0 and the for loop ends.
     
    jmcgill, Oct 10, 2006
    #10
  11. jmcgill Guest

    Clever Monkey wrote:

    > So, we loop through the char array, getting the _th item in the array,
    > subtracting 1 and printing the char we get. I suppose this presumes
    > ASCII collation.


    Shouldn't a non-ASCII implementation do the right thing, where 'b' -1 =
    'a', regardless of the inner details?
     
    jmcgill, Oct 10, 2006
    #11
  12. Richard Bos Guest

    jmcgill <> wrote:

    > Clever Monkey wrote:
    >
    > > So, we loop through the char array, getting the _th item in the array,
    > > subtracting 1 and printing the char we get. I suppose this presumes
    > > ASCII collation.

    >
    > Shouldn't a non-ASCII implementation do the right thing, where 'b' -1 =
    > 'a', regardless of the inner details?


    No. Read the Standard. Only '0'...'9' are required to be subsequent. The
    rest need not, and often _but not always_ is subsequent.

    Richard
     
    Richard Bos, Oct 10, 2006
    #12
  13. Aarklon posted:

    > main(_) {for(--_;putchar(_++["J!Mpwf!Zpv\1"]-1););}



    (1) If we replace the underscore object name with "i", then we get:

    main(i) {for(--i;putchar(i++["J!Mpwf!Zpv\1"]-1););}


    (2) If we make explicit the implicit int:

    int main(int i) {for(--i;putchar(i++["J!Mpwf!Zpv\1"]-1););}


    (3) If we put in white space to make things prettier:

    int main(int i)
    {
    for( --i; putchar(i++["J!Mpwf!Zpv\1"]-1); ) ;
    }


    (4) If we take "i" out of the loop, and then change it to a "while" loop:

    int main(int i)
    {
    --i;

    while( putchar(i++["J!Mpwf!Zpv\1"]-1); );
    }


    (5) If we change "index[array]" to "array[index]", then we have:

    int main(int i)
    {
    --i;

    while( putchar( "J!Mpwf!Zpv\1"[i++] - 1) );
    }


    (6) If we take the take the string out of the loop to make it clearer:

    int main(int i)
    {
    char const str[] = "J!Mpwf!Zpv\1";

    --i;

    while (putchar(str[i++] - 1));
    }

    Armed with the knowledge that "putchar" returns the char it prints, we can
    see that we are iterating through each character of the string, subtracting
    one from it, then printing it.

    The code is non-portable as it makes the unfounded presumption that:

    'J' == 'I'+1

    Also, I'm not sure if that's a valid signature for "main".

    --

    Frederick Gotham
     
    Frederick Gotham, Oct 10, 2006
    #13
  14. Flash Gordon Guest

    Clever Monkey wrote:
    > wrote:
    >> Hi all,
    >>
    >> can anybody please explain why this code
    >>
    >> main(_) {for(--_;putchar(_++["J!Mpwf!Zpv\1"]-1););}
    >>
    >> is producing the output:: I love you
    >>
    >>

    > I'll bite. I might be wrong, but I'll bite.
    >
    >> 1) what is this under score stuff inside main parenthesis?

    > It is an illegal (I presume) reference to something like argc. It is
    > similar to "main(int _)", but very non-standard.


    Actually, the function definition form
    foo(arg) {}
    Is entirely legal and standard C89 since C89 still allows implicit int
    and old K&R style function definitions. The problem is that main takes 0
    or 2 arguments, not one. This could be fixed by changing it to

    main(_,__)char**__;{for(--_;putchar(_++["J!Mpwf!Zpv\1"]-1););}
    which still keeps it obfusticated.

    You can get C99 compliance with
    #include<stdio.h>
    int main(_,__)int
    _;char**__;{for(--_;putchar(_++["J!Mpwf!Zpv\1"]-1););}

    > I expect for those compilers that accept this will set "_" to 1 before
    > we visit the for loop.


    <snip>

    Unless the user supplies parameters or the environment chooses not to
    pass something as the "program name".
    --
    Flash Gordon
     
    Flash Gordon, Oct 10, 2006
    #14
  15. Flash Gordon wrote:
    > Clever Monkey wrote:
    >> wrote:
    >>> can anybody please explain why this code
    >>>
    >>> main(_) {for(--_;putchar(_++["J!Mpwf!Zpv\1"]-1););}
    >>>
    >>> is producing the output:: I love you
    >>>
    >>> 1) what is this under score stuff inside main parenthesis?

    >> It is an illegal (I presume) reference to something like argc. It is
    >> similar to "main(int _)", but very non-standard.

    >
    > Actually, the function definition form
    > foo(arg) {}
    > Is entirely legal and standard C89 since C89 still allows implicit int
    > and old K&R style function definitions. The problem is that main takes 0
    > or 2 arguments, not one. This could be fixed by changing it to
    >
    > main(_,__)char**__;{for(--_;putchar(_++["J!Mpwf!Zpv\1"]-1););}
    > which still keeps it obfusticated.
    >

    Sure. This is what I meant by "non-standard", since the main() is
    malformed and incorrect with respect to the standard. I do understand
    that this is a _mostly_ legal function definition; just not for the
    function main(). Note my reference to "argc", above.

    Furthermore, wasn't there just a thread here about the use of "_" and
    "__" being forbidden by the standard under most circumstances? I
    suppose an identifier that consists only of these characters would be
    contrary to that rule, as well.

    Again, this does not speak to the OP, but it indicates that many things
    about "main(_)" are probably wrong, regardless of the fact that main()
    can be treated just like another function in many cases and that the
    default type for untyped identifiers is int.
     
    Clever Monkey, Oct 10, 2006
    #15
  16. Simon Biber Guest

    wrote:
    > Hi all,
    >
    > can anybody please explain why this code
    >
    > main(_) {for(--_;putchar(_++["J!Mpwf!Zpv\1"]-1););}
    >
    > is producing the output:: I love you


    It doesn't produce that output. The L and Y are capitalised.

    If you supply arguments to the program, one letter is lost from the
    beginning for each argument you supply. If you supply more than 10
    arguments, the program outputs garbage until a 1 byte is found in memory
    or the program attempts to read an invalid address and is terminated.


    C:\docs\prog\c>type aarklon.c
    #include <stdio.h>
    main(_){for(--_;putchar(_++["J!Mpwf!Zpv\1"]-1););}

    C:\docs\prog\c>tcc aarklon.c
    Turbo C Version 2.01 Copyright (c) 1987, 1988 Borland International
    aarklon.c:
    Turbo Link Version 2.0 Copyright (c) 1987, 1988 Borland International

    Available memory 394258

    C:\docs\prog\c>aarklon 1 2 3 4 5 6 7 8 9 0 1
    ↕☺☺♥♦♣‼¶♦↕■§♦►☺■■■■■■■■■■■■■♦♦■■■■■■■■■■■■■■■■♫■"☺■♫■■■■↕■■☺☺♦♫☺■■■↕■■■■■■■■
    "■■■■"■↕■ z☺z☺z☺ ☼ ☺ ‼☺

    --
    Simon.
     
    Simon Biber, Oct 10, 2006
    #16
  17. Frederick Gotham wrote:

    > The code is non-portable as it makes the unfounded presumption that:
    >
    > 'J' == 'I'+1



    Ah yes, any computers out there using the 5-bit Baudot code are going
    to print complete gibberish.

    Seriously, in IBM EBCDIC, the letters are not contiguous, due to it
    being derived from BCD card codes, which as everybody knows, had nine
    rows, so the letters are in groups of nine, with seven codes in between
    to pad to the next multiple of 16.

    But due to pure chance, most of the letters in this phrase are
    comfortably away from the abrupt jumps. The only problem is with the
    initial "J", which one less than is "}".


    Also space is not just before exclamation point, Ampersand is. Also
    the ending period gets messed up.

    So in EBCDIC it will print out:

    }&love&you|
     
    Ancient_Hacker, Oct 10, 2006
    #17
  18. Ancient_Hacker posted:

    > Ah yes, any computers out there using the 5-bit Baudot code are going
    > to print complete gibberish.



    Exactly (assuming Baudot code has at least 3 unused bits).


    > Seriously, in IBM EBCDIC, the letters are not contiguous, due to it
    > being derived from BCD card codes, which as everybody knows, had nine
    > rows, so the letters are in groups of nine, with seven codes in between
    > to pad to the next multiple of 16.



    Your use of "Seriously" is not necessary here at comp.lang.c, nor is it even
    necessary to provide an example (although I'm glad you did :) ). All we need
    to hear is "The Standard doesn't impose such a restriction" and we're bought.

    --

    Frederick Gotham
     
    Frederick Gotham, Oct 10, 2006
    #18
  19. Flash Gordon Guest

    Clever Monkey wrote:
    > Flash Gordon wrote:
    >> Clever Monkey wrote:
    >>> wrote:
    >>>> can anybody please explain why this code
    >>>>
    >>>> main(_) {for(--_;putchar(_++["J!Mpwf!Zpv\1"]-1););}
    >>>>
    >>>> is producing the output:: I love you
    >>>>
    >>>> 1) what is this under score stuff inside main parenthesis?
    >>> It is an illegal (I presume) reference to something like argc. It is
    >>> similar to "main(int _)", but very non-standard.

    >>
    >> Actually, the function definition form
    >> foo(arg) {}
    >> Is entirely legal and standard C89 since C89 still allows implicit int
    >> and old K&R style function definitions. The problem is that main takes
    >> 0 or 2 arguments, not one. This could be fixed by changing it to
    >>
    >> main(_,__)char**__;{for(--_;putchar(_++["J!Mpwf!Zpv\1"]-1););}
    >> which still keeps it obfusticated.
    >>

    > Sure. This is what I meant by "non-standard", since the main() is
    > malformed and incorrect with respect to the standard. I do understand
    > that this is a _mostly_ legal function definition; just not for the
    > function main(). Note my reference to "argc", above.


    OK, then we are in agreement about what is and is not valid.

    > Furthermore, wasn't there just a thread here about the use of "_" and
    > "__" being forbidden by the standard under most circumstances? I
    > suppose an identifier that consists only of these characters would be
    > contrary to that rule, as well.


    You are right, I should not have used __. Perhals _l or _L would be
    sufficiently obscure. That will teach me to rely on memory for a rule
    like this. Normally I just don't start identifiers with an _ even where
    it would be legal.

    > Again, this does not speak to the OP, but it indicates that many things
    > about "main(_)" are probably wrong, regardless of the fact that main()
    > can be treated just like another function in many cases and that the
    > default type for untyped identifiers is int.


    Well, the _ on its own is acceptable as an identifier as long as it is
    not a file scope identifier which it isn't.
    --
    Flash Gordon
     
    Flash Gordon, Oct 10, 2006
    #19
  20. On Tue, 10 Oct 2006 08:41:07 -0700, in comp.lang.c , jmcgill
    <> wrote:

    >Clever Monkey wrote:
    >
    >> So, we loop through the char array, getting the _th item in the array,
    >> subtracting 1 and printing the char we get. I suppose this presumes
    >> ASCII collation.

    >
    >Shouldn't a non-ASCII implementation do the right thing, where 'b' -1 =
    >'a', regardless of the inner details?


    No, this isn't required by the Standard, and indeed realworld
    implementations will break this assumption (think non-english
    character sets, or EBCDIC or whatever)
    --
    Mark McIntyre

    "Debugging is twice as hard as writing the code in the first place.
    Therefore, if you write the code as cleverly as possible, you are,
    by definition, not smart enough to debug it."
    --Brian Kernighan
     
    Mark McIntyre, Oct 10, 2006
    #20
    1. Advertising

Want to reply to this thread or ask your own question?

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. Replies:
    0
    Views:
    694
  2. chris kramer
    Replies:
    5
    Views:
    594
    chris kramer
    Apr 9, 2004
  3. fix

    Obfuscated xsl

    fix, Nov 27, 2003, in forum: XML
    Replies:
    4
    Views:
    607
    Patrick TJ McPhee
    Nov 28, 2003
  4. Thomas Garai

    obfuscated c/c++

    Thomas Garai, Jun 22, 2004, in forum: C++
    Replies:
    5
    Views:
    493
    Prateek R Karandikar
    Jun 22, 2004
  5. G. Nick D'Andrea

    Obfuscated Languages Interpreter

    G. Nick D'Andrea, Jun 30, 2003, in forum: C Programming
    Replies:
    3
    Views:
    754
    David Rubin
    Jul 2, 2003
Loading...

Share This Page