管道回声到gcc?

时间:2017-12-27 23:30:07

标签: c gcc compilation pipe

要从终端呼叫C中的printf("Hello!");,请使用

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

然后调用gcc foo.c进行输出。不幸的是,流水线

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

无法抱怨没有输入文件。最后,我希望有一个脚本,我可以使用command从终端编译C ./script [command]。任何建议将不胜感激。

4 个答案:

答案 0 :(得分:4)

是的,但您必须使用-x选项指定语言。使用-xc将输入文件指定为stdin,将语言指定为C(如果您希望它是C ++,则使用,使用-xc++ )。因此,在您的情况下,命令将是

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

您可以阅读有关Command Line Compiler Arguments的更多信息:请参阅Invoking GCC章节。

然而,正如@Basile所说,不值得努力避免处理C文件。检查他的答案以获取更多信息。

答案 1 :(得分:2)

我过去做过

ln -s /dev/stdin stdin.c

现在stdin.c/dev/stdin的符号链接,即魔术文件&#34;包含&#34;我打字或管道的任何东西。但文件名以.c结尾,因此任何C编译器都应将其视为C文件。像

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

工作得很好。

(显然,这假设您使用的是具有符号链接和/dev/stdin的类Unix系统。)

答案 2 :(得分:2)

Other答案解释了如何让gcc stdin 中读取C代码,但请注意在实践中不值得努力避免处理C文件

(我猜您正在使用某些类似Linux的POSIX操作系统;如果没有,请根据您的操作系统和编译器调整我的答案)

自动发送C代码是常用做法(许多学术编程语言都是compiling to C,许多构建使用生成的C代码,例如来自bison)。但是使用管道和 stdin 没有多大好处,因为C编译器需要花费大量时间(特别是optimization,这是您经常需要的,例如通过编译{{1} })。

所以我的建议是将生成的C代码放在一个真正的文件中(也许是一些临时文件,应该在以后适当删除)。如果磁盘性能存在问题,那么该文件可能位于某个tmpfs文件系统上(实际上它永远不会用于gcc -O2已编译的源代码),并且该文件可能是临时的(例如,以后删除)想要它。

请注意,gcc程序通常在内部使用临时文件(例如,用于生成的汇编程序文件或目标文件)。如果您将gcc添加到-v编译命令,例如,您就会看到它们。如果您使用gcc汇编foo.c。所以没有实际的理由避免使用C源文件(因为gcc -v foo.c -o fooprog使用临时文件!)。

如果要在正在运行的程序中动态生成代码,可以生成临时C代码,然后将其编译为临时plugin(使用position-independent code)然后dynamically load该插件(例如在Linux上使用dlopen(3)&amp; dlsym(3));但您也可以使用JIT compilingGCCJITLLVMasmjit库等。当然,这需要您operating system的一些支持(例如增长virtual address space):在纯标准C11(阅读n1570)中,函数集在构建时固定,因为在translation units的联合中定义了gcc个文件集,并且您无法在运行时生成代码。

如果你想在某些shell script中生成一些C程序,最好使用临时文件,例如使用.ctempfile等...(并在mktempEXIT信号上使用trap builtin以在脚本终止时删除临时文件。 / p>

如果您在build中生成了一些临时C代码,则可以配置好的build automation程序(例如GNU makeninja)来删除这些临时C文件(例如阅读TERM的{​​{3}}。

还要研究像Common Lisp这样的intermediate files编程语言。例如,homoiconic在每次SBCL交互时都会编译成机器代码。

答案 3 :(得分:0)

为什么不让脚本运行命令,而不是管道它:

gcc foo.c

同时仍然保持重定向到foo.c

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

如果您希望在gcc创建可执行文件之后通过在末尾添加

,则可以删除foo.c.
rm foo.c