Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

print "hello world!" using read in C [closed]

Tags:

c

I saw this in the ioccc.

    int i;
    main()
    {
        for(;i["]<i;++i){--i;}"];read('-'-'-',i+++"hello, world!\n",'/'/'/'));
    }
    read(j,i,p)
    {
        write(j/p+p,i---j,i/i);
    }

It prints out 'hello world!' when compiled with gcc, unsure if it works with visual studio 12. Can somebody explain to me how the hell it works??

like image 532
user1461607 Avatar asked Dec 13 '25 08:12

user1461607


1 Answers

Since original code was removed from the question and reformatted one been substituted instead, i start with the code as it was given by the topic starter.

int i;main(){for(;i["]<i;++i){--i;}"];
read('-'-'-',i+++"hello, world!\n",'/'/'/'));
}read(j,i,p){write(j/p+p,i---j,i/i);}

Start with recovering the structure. Add spaces and line breaks where they belong to. Remember that C assumes int data type when not specified.

int i;

/* int */ main()
{
  for( ; i["]<i;++i){--i;}"];
          read(   '-' - '-',
                   i++ + "hello, world!\n",
                   '/' / '/') );
}

/* int */ read( /* int */ j,i,p)
{
  write( j/p + p, i-- - j, i/i );
}

Take note that in C the language:

  1. there is no "character" type. A letter is just a (typically 8 bits) integer. Thus '-' - '-' is zero and '/' / '/' is 1 (just like i/i later)
  2. there is no "string" type - that is just a pointer to "character"
  3. arrays and pointers are the same thing by definition
  4. no-sized (byte-sized) pointers and integers are implicitly converted to each other.

Note: in comments below people argue that in C array are not pointers but are just implicitly typecasted to pointers. That is probably true in theory, yet doesn't seem to have any practical implication for this certain code. But still, a bullet 3 is perhaps formulated incorrectly by book.

Also let us assume that all global variables are zero-initialized.

Thus i["]<i;++i){--i;}"] is 0[pointer to some string], then 1[pointer to some string], etc. Effectively being the i-th character of the string.
It is used in a for-loop at the second parameter place - the condition checker. So actually this can be re-formulated as

for( ; "]<i;++i){--i;}"[i] != '\0'; read... );

or by definition of C for loop

while ( "]<i;++i){--i;}"[i] != 0 ) { read ...; }

It is not a coinsidence, that both lines have equally 14 characters:
"hello, world!\n"
"]<i;++i){--i;}"

That makes it just a loop for each character in string, you could re-formulate it as
for i := 0 to 14-1 do

Glue this all together and the program turns into

int i;

/* int */ main()
{
  for( i=0; i<strlen("hello, world!\n"); i++)
  {
    read( 0, & "hello, world!\n"[i], 1);
  }
}

Is it a bit easier? Now moving to the function itself... and to C file handles. By UNIX standard, the following text files are pre-defined:

  • 0 - STDIN - read from keyboard
  • 1 - STDOUT - print to display/printer/log-file/etc
  • 2 - STDERR - emergency print about error conditions

Thus:

/* int */ read( j = 0, i = pointer-to-letter-to-print, p = 1)
{
  write( j/p + p, // 0/1 + 1  == 1 == STDOUT 
         i-- - j, // == i itself due to j == 0; 
                  // -- is POST-decrement and does not affect the calculation
         i/i /*== 1 as long as i != 0  - meaning print only single character*/ );
}

Gluing this together again:

int i;

int my_read( int j, char * pChar, int p)
{
  write( STDOUT, pChar, 1 );
  pChar--; // does not affect anything, as mentioned above
}

const char msg[] = "hello, world!\n";
int main(void)
{
  for( i=0; i<strlen(msg); i++)
  {
    my_read( 0, &msg[i], 1);
  }
}

Can you figure out how this snippet works now? ;-)

Just add spaces and new lines - the proper code structure formatting - and it becomes easy-peesy :-)

like image 115
Arioch 'The Avatar answered Dec 15 '25 02:12

Arioch 'The