C Код: Как они работают?

Я только что увидел это здесь

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

Что это значит, это «Hello World!».

Но что здесь происходит?

Лучшее, что я могу догадаться, это то, что он компилируется и бросается в верхнюю часть стека выполнения, но синтаксис даже не выглядит законным для меня …

    В коде используется функция массива переменной длины C99, которая позволяет объявлять массивы, размер которых известен только во время выполнения. printf возвращает целое число, равное количеству символов, которые были на самом деле напечатаны, поэтому код печатает «Hello, world!». сначала и использует возвращаемое значение как размер argv . Сама main функция ничего не делает. Фактический вызов printf сам, вероятно, входит в код запуска, сгенерированный компилятором, который, в свою очередь, вызывает main .

    Изменить: я просто проверил parsing кода, сгенерированного gcc и выяснилось, что вызов printf проходит внутри самого main , перед любым другим кодом.

    Если я выясню, как компилятор проанализировал его, я обновлю это, но, по крайней мере, не должно быть никаких догадок о том, как он скомпилирован:

     objdump --disassemble /tmp/hello (edited): 080483c4 
    : 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 80483da: c9 leave 80483db: c3 ret 80483dc: 90 nop 80483dd: 90 nop 80483de: 90 nop 80483df: 90 nop

    Поскольку исполняемые файлы Linux обычно основаны на 0x8048000, адрес аргумента printf имеет смещение 0x00004a0 с начала двоичного файла:

     xxd /tmp/hello | grep 00004a0 00004a0: 4865 6c6c 6f2c 2077 6f72 6c64 210a 0000 Hello, world!... 

    Таким образом, адрес строки выталкивается, а printf вызывается с одним аргументом. Ничего волшебного на этом уровне, поэтому все забавные вещи были сделаны gcc.

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

    printf() возвращает количество напечатанных символов.

    Так

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

    эквивалентно

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

    плюс вызов printf() который печатает "Hello World"

    Я не эксперт от C, но похоже, что аргументы командной строки объявляются одновременно с main .