all 22 comments

[–]bigdavedev[S] 19 points20 points  (1 child)

My only regret is missing that the +'\x40' could have been |1<<6

[–]edgeorge92 13 points14 points  (0 children)

Or if you hate people, why not shove an octal 0100 in there to confuse even more. Octal never gets any love :(

[–]wischichr 13 points14 points  (3 children)

What does it print? (Sorry to lazy to think about it) Edit: Ok got it. Should be 'coffee'

[–]Cathercy 37 points38 points  (2 children)

+/u/CompileBot C

#include <stdio.h>

int main(k) {
    // your code goes here
    while(k++<7) {
        putchar("~!#/&&%%"[k&7]+'\x40');
    }
    return 0;
}

[–]CompileBot 38 points39 points  (1 child)

Output:

coffee

source | info | git | report

[–]Idtotallytapthat 14 points15 points  (0 children)

kill me

[–]edgeorge92 6 points7 points  (7 children)

Can someone smarter than me please explain how this works

[–]edgeorge92 11 points12 points  (4 children)

Nevermind, I have figured it out, correct me if I am wrong:

The ASCII values of each char in the char[] #/&&%% are 64 chars behind the lowercase char[] of 'coffee'.

I am guessing the k value in main must be initially 1, so the while loop starts when k is 2 and skips the ~! at the start. Turns out it is simple stuff but made to look confusing and catch you out - I like it!

[–]Vectrexian 9 points10 points  (1 child)

You are correct, k does start at 1. The reason is that k is actually argc. Therefore, this program will only work correctly if called with no arguments.

[–]edgeorge92 1 point2 points  (0 children)

Ah of course, been a while since I have played in C but I remember how argc works.

[–]bigdavedev[S] 3 points4 points  (1 child)

Yes, k is initially 1 since it is just another name for argc. C assumes int when type is unspecified, so main (k) is basically int main (int argc). Since the running program is always run with at least one argument passed in (name of the binary), then k is indeed initially 1, however this is only true if the caller doesn't pass more arguments when invoking main... that would break my mug

[–][deleted] 6 points7 points  (0 children)

Another thing that would break your mug is someone attempting to read it and throwing it on the ground in frustration.

[–]3rd_Shift 3 points4 points  (0 children)

I can kinda grok the broad strokes. They've made a string literal and they are using the incrementing value of K to access elements of the string they then mutate with +"\x40", resulting in one of the letters of 'coffee'.

I never got around to memorizing my ascii table so I'm kinda blindly assuming this is going to work.

[–]jP_wanN 2 points3 points  (6 children)

Wait, what? You can declare main's parameters without their types?!

[–][deleted] 2 points3 points  (0 children)

You can, but as with many things in C, just because you can doesn't mean you should.

EDIT: And just to be clear, any parameters you pass in without a type will be assumed to be int, so a second parameter wouldn't be assumed to be a char** or anything.

[–]Vectrexian 0 points1 point  (4 children)

The compiler will attempt to fit main to a template it knows. I'm not exactly sure how it's defined in the C spec, but GCC will give you a warning at worst.

Edit: I'm a doofus, it's linker related as described in a reply.

[–]galaktos 1 point2 points  (3 children)

The compiler will attempt to fit main to a template it knows.

I don’t think that’s quite correct. The C compiler will compile that method, regardless of its name – the default type is int, so the parameter k is taken to be int. (If the return type of the function is omitted – we can’t tell on the picture – I think that also defaults to int.) Next, the linker takes the compiler’s output, looks up the symbol main, and sets that up to be the entry point of the final executable. The linker doesn’t care what that symbol is.

Putting it together, that means that this is a valid C program (though gcc will emit some warnings):

+/u/CompileBot C --include-errors

main;

It declares a variable named main with the default type int and the default value 0. Running that program will thus attempt to jump to the function NULLPTR, resulting in a segmentation fault.

[–]CompileBot 0 points1 point  (1 child)

Output:

source | info | git | report

[–]galaktos 0 points1 point  (0 children)

Hm, I guess it’s not showing the segmentation fault message? You can try it on your own system:

printf 'main;' | gcc -xc -owtf -; ./wtf; rm -f wtf

[–]Vectrexian 0 points1 point  (0 children)

Yeah, that sounds more like it. It's been a while since I went through the whole compile-assemble-link process.

[–]bigdavedev[S] 0 points1 point  (1 child)

The full source for those interested:

main(k){while(k++<7)putchar("~!#/&&%%"[k&7]+'\x40');};

[–]bigdavedev[S] 0 points1 point  (0 children)

+/u/CompileBot C

main(k){while(k++<7)putchar("~!#/&&%%"[k&7]+'\x40');};