C Code: How does these even work?

别来无恙 提交于 2019-12-31 12:07:36

问题


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 ...


回答1:


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.




回答2:


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.




回答3:


char *argv[printf("Hello, world!\n")])

printf() returns the number of characters printed.

So

int main(int argc, char *argv[printf("Hello, world!\n")]) {}

is equivalent to

int main(int argc, char *argv[14]) {}

plus a call to printf() which prints "Hello World"




回答4:


I'm no C expert, but it looks like the command line arguments are declared at the same time as main.



来源:https://stackoverflow.com/questions/4151115/c-code-how-does-these-even-work

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!