I just saw this here
#include <stdio.h> int main(int argc, char *argv[printf("Hello, world!\n")]) {}
What this does is print "Hello World!"
But what's actually going on here?
The best I can guess is that it gets compiled and thrown at the top of the execution stack, but the syntax doesn't even look legal to me ...
c is called the source file which keeps the code of the program. Now, when we compile the file, the C compiler looks for errors. If the C compiler reports no error, then it stores the file as a . obj file of the same name, called the object file.
C is one of the earliest and most widely used programming languages. C is the fourth most popular programming language in the world as of January 2022. Modern languages such as Go, Swift, Scala, and Python are not as popular as C.
Less than or equal to operator is a logical operator that is used to compare two numbers.
C is more difficult to learn than JavaScript, but it's a valuable skill to have because most programming languages are actually implemented in C. This is because C is a “machine-level” language. So learning it will teach you how a computer works and will actually make learning new languages in the future easier.
The code makes use of C99's variable-length array feature, which lets you declare arrays whose size is known only at run-time. printf
returns an integer equal to the number of characters that were actually printed, so the code prints "Hello, world!" first and uses the return value as the size of argv
. The main
function itself does nothing. The actual call to printf
itself probably goes into the startup code generated by the compiler, which in turn calls main
.
Edit: I just checked the disassembly of the code generated by gcc
and it appears that the call to printf
goes inside main
itself, before any other code.
If I figure out how the compiler parsed it, I'll update this, but at least there needs to be no guesswork as to how it compiled:
objdump --disassemble /tmp/hello (edited): 080483c4 <main>: 80483c4: 55 push %ebp 80483c5: 89 e5 mov %esp,%ebp 80483c7: 83 e4 f0 and $0xfffffff0,%esp 80483ca: 83 ec 10 sub $0x10,%esp 80483cd: b8 a0 84 04 08 mov $0x80484a0,%eax 80483d2: 89 04 24 mov %eax,(%esp) 80483d5: e8 22 ff ff ff call 80482fc <printf@plt> 80483da: c9 leave 80483db: c3 ret 80483dc: 90 nop 80483dd: 90 nop 80483de: 90 nop 80483df: 90 nop
Since Linux executables are based normally at 0x8048000, the address of the argument to printf is at an offset of 0x00004a0 from the start of the binary:
xxd /tmp/hello | grep 00004a0 00004a0: 4865 6c6c 6f2c 2077 6f72 6c64 210a 0000 Hello, world!...
So, the address of the string is pushed, and printf is called with that one arg. Nothing magical at that level, so all the fun stuff was done by gcc.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With