@TIZ большое спасибо за ваш ответ. И спасибо вам обоим за то, что нашли время прочитать мой вопрос. Джонатан прав: я искал способ генерировать код на лету и думал о конвейерах как о логическом подходе. Извините, если я создал путаницу, не упомянув это явно в моем вопросе.

тьprintf("Hello!"); в C из терминала я использую

echo '#include<stdio.h>
void main()
{
printf("Hello!");
}' > foo.c

а затем позвонитеgcc foo.c сделать вывод. К сожалению, конвейер

echo '#include<stdio.h>
void main()
{
printf("Hello!");
}' | gcc 

не жалуется на отсутствие входного файла. В конечном счете, я хочу иметь скрипт, где я могу скомпилировать Ccommand от терминала с./script [command], Любое предложение будет оценено.

 Steve Summit28 дек. 2017 г., 08:31
@klutt В общем, трубопроводы - это хорошо. В общем, любая программа должна принимать ввод от stdin, если у нее нет веских причин не делать этого. Тот факт, что вы не можете придумать, как его использовать, не означает, что иметь универсальные возможности не очень хорошая идея. (Теперь, с учетом сказанного, я согласен, что трудно представить себе ситуацию, когда вам действительно нужно было бы передать код C в компилятор C. Я реализовал трюк с символьной ссылкой - как описано в ответе - много лет назад , просто для удовольствия, но я не думаю, что когда-либо использовал это.)
 Broman28 дек. 2017 г., 01:01
Могу ли я спросить, когда вы хотите сделать это? Я не вижу никакого смысла в этом.
 Basile Starynkevitch28 дек. 2017 г., 08:25
@klutt: если код C сгенерирован какой-то программой, вы можете сделать это. Но действительно, это не стоит боли

Ответы на вопрос(4)

gcc foo.c

сохраняя перенаправление в foo.c

echo '#include<stdio.h> 
void main()
{
printf("Hello!");
}' > foo.c
gcc foo.c

Затем вы можете удалить foo.c, если хотите, после того как gcc создаст исполняемый файл, добавив в конце

rm foo.c
 Jonathan Leffler28 дек. 2017 г., 00:47
Это то, что описано в первой части вопроса, а не то, что пользователь хочет в долгосрочной перспективе. Вопрос в том, как этого добиться, не создавая промежуточный файл.foo.c
 TIZ29 дек. 2017 г., 01:24
Из его комментариев я не вижу ограничения ни для каких промежуточных файлов. Это было бы решением его вопроса.
 Masoud Ghaderi29 дек. 2017 г., 12:19
@TIZ большое спасибо за ваш ответ. И спасибо вам обоим за то, что нашли время прочитать мой вопрос. Джонатан прав: я искал способ генерировать код на лету и думал о конвейерах как о логическом подходе. Извините, если я создал путаницу, не упомянув это явно в моем вопросе.
 Jonathan Leffler29 дек. 2017 г., 01:28
В этом вопросе я вижу «К сожалению, конвейерная обработка… не удается», что указывает на то, что он не хочет промежуточного файла. И этот вопрос ясно показывает, что он знает, как создать промежуточный файл.
 TIZ29 дек. 2017 г., 02:08
Не уверен, как это указывает на то, что он не хочет промежуточного файла. Я вижу, что он может создать промежуточный файл, но передача прав на gcc без аргументов заставила меня думать, что простого решения, подобного этому, будет достаточно. Я просто отвечал на вопрос, как он был задан. Для меня это выглядит так: «В конечном счете, я хочу иметь скрипт, в котором я могу скомпилировать команду C из терминала с помощью ./script [команда]», опять же, я не вижу ограничений, которые вы описали. - Если я неправильно истолковал вопрос, тогда извините.
Решение Вопроса

Да, но вы должны указать язык, используя-x вариант. Укажите входной файл как stdin, язык как C, используя-xc (если вы хотите, чтобы это был C ++, используйте-xc++). Так что в вашем случае команда будет

echo '#include<stdio.h>
void main()
{
printf("Hello!");
}' | gcc -o output.o -xc -

Вы можете прочитать больше оАргументы компилятора командной строки: видетьВызов GCC глава.

Однако, как говорит @Basile,Это не стоит усилий, чтобы избежать работы с файлами C, Проверьте его ответ для получения дополнительной информации.

Я делал это в прошлом, делая

ln -s /dev/stdin stdin.c

В настоящее времяstdin.c символическая ссылка на/dev/stdinто есть волшебный файл, «содержащий» все, что я набираю или передаю ему. Но имя файла заканчивается.c, поэтому любой компилятор C должен рассматривать его как файл C. Вещи как

(echo '#include <stdio.h>'
 echo 'int main(void) { printf("Hello, world!\n"); }') |
    cc stdin.c

работать просто отлично.

(Очевидно, это предполагает, что вы используете Unix-подобную систему с символическими ссылками и/dev/stdin.)

Другие ответы объясняют, как сделатьgcc читать код C изSTDIN, но обратите внимание, что на практике
Это не стоит усилий, чтобы избежать работы с файлами C.

(Я предполагаю, что вы используете какую-то операционную систему POSIX, например Linux; если нет, адаптируйте мой ответ к вашей ОС и компилятору)

Испускание кода C автоматически является обычной практикой (и многие академические языки программированиякомпиляция в Cи во многих сборках используется сгенерированный C-код, например, избизон). Но нет большой выгоды использовать трубы иSTDINпотому что компилятор C занимает много времени (особенно дляоптимизациячто вы часто хотите, например, путем компиляции сgcc -O2).

Поэтому я рекомендую поместить сгенерированный код C в подлинный файл (возможно, временный, который следует соответствующим образом удалить позже). Этот файл может быть на некоторыхTMPFS файловая система, если производительность диска является проблемой (и на практике это никогда неgcc скомпилированный исходный код), и этот файл может быть временным (например, удаленным позже), если вы этого хотите.

Обратите внимание, чтоgcc Программа, как правило, сама использует временные файлы (например, для сгенерированных файлов ассемблера или объектных файлов). Вы увидите их, если добавите-v на вашgcc команда компиляции, например если вы компилируетеfoo.c с участиемgcc -v foo.c -o fooprog, Таким образом, нет практической причины избегать исходного файла C (так какgcc использует временныйфайлы так или иначе!).

Если вы хотите генерировать код на лету в работающей программе, вы можете сгенерировать временный код C, а затем скомпилировать его как временныйплагин (с участиемпозиционно-независимый код) тогдадинамически загружать этот плагин (например, используяdlopen (3) & dlsym (3) в Linux); но вы также можете использоватьJIT компиляция библиотеки какGCCJIT или жеLLVM или жеasmjitи т.д. .... Конечно, это требует некоторой поддержки от вашегооперационная система (например, чтобы выраститьвиртуальное адресное пространство): в чистом видеC11 (читатьn1570), набор функций фиксируется во время сборки, так как определено в объединении вашихпереводческие единицы (набор.c файлы, составляющие вашу программу), и вы не можете генерировать код во время выполнения.

Если вы хотите сгенерировать некоторую программу на C в некоторыхсценарий оболочкилучше использовать временные файлы, например с участиемtempfile, mktemp и т.д ... (и использоватьtrap встроенная наEXIT и наTERM сигнал на удаление временных файлов при завершении скрипта).

Если вы генерируете некоторый временный код C в вашемстроить, хорошийавтоматизация сборки программы (например,GNUmake или жеninja) можно настроить для удаления этих временных файлов C (например, прочитать опромежуточные файлы заmake).

Смотрите также вhomoiconic языки программирования, такие как Common Lisp. НапримерSBCL компилируется в машинный код на каждомРЕПЛ взаимодействие.

Ваш ответ на вопрос