C Код: Как они работают?
Я только что увидел это здесь
#include <stdio.h>
int main(int argc, char *argv[printf("Hello, world!\n")]) {}
Что это значит, это "Hello World!"
Но что на самом деле происходит здесь?
Самое лучшее, что я могу догадаться, это то, что он скомпилирован и добавлен в верхнюю часть стека выполнения, но синтаксис даже не выглядит законным для меня...
Ответы
Ответ 1
В коде используется функция массива переменной длины C99, которая позволяет объявлять массивы, размер которых известен только во время выполнения. printf
возвращает целое число, равное количеству символов, которые были на самом деле напечатаны, поэтому код печатает "Hello, world!". сначала и использует возвращаемое значение как размер argv
. Сама функция main
ничего не делает. Фактический вызов printf
сам, вероятно, входит в код запуска, сгенерированный компилятором, который, в свою очередь, вызывает main
.
Изменить: Я только что проверил разбор кода, сгенерированного gcc
, и кажется, что вызов printf
входит внутрь main
непосредственно перед любым другим кодом.
Ответ 2
Если я выясню, как компилятор проанализировал его, я обновлю это, но, по крайней мере, не должно быть никаких догадок о том, как он скомпилирован:
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 <[email protected]>
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.
Ответ 3
char *argv[printf("Hello, world!\n")])
printf()
возвращает количество напечатанных символов.
So
int main(int argc, char *argv[printf("Hello, world!\n")]) {}
эквивалентно
int main(int argc, char *argv[14]) {}
плюс вызов printf()
, который печатает "Hello World"
Ответ 4
Я не эксперт от C, но похоже, что аргументы командной строки объявляются одновременно с main
.