Linux C:类似shell的环境——对于单个执行的C命令?(C解释器)

时间:2021-03-21 23:24:30

Sorry if the question is worded wrong - I don't know the right word for what I'm asking for! :)

对不起,如果这个问题是错误的——我不知道我要的是什么词!:)

Say, you have some simple C program like:

比如,你有一些简单的C程序,比如:

#include <stdio.h>

int main()
{
   int a=2; 
   printf("Hello World %d\n", a);
   return 0;
} 

Typically, this would have to be saved in a file (say, hello.c); then we run gcc on the source file and obtain executable file - and if we compiled in debug information, then we can use gdb on the executable, to step through lines of code, and inspect variables.

通常,这必须保存在一个文件中(例如,hello.c);然后,我们在源文件上运行gcc并获得可执行文件——如果我们在调试信息中编译,那么我们可以在可执行文件上使用gdb,以遍历代码行,并检查变量。

What I would like to have, is basically some sort of a "C" shell - similar to the Python shell; in the sense that I can have a sequence of Python commands in a file (a script) - or I can just paste the same commands in the shell, and they will execute the same. In respect to the simple program above, this is what I'd like to be able to do (where C> represents the imagined prompt):

我想要的,基本上是某种“C”shell——类似于Python shell;在某种意义上,我可以在一个文件(脚本)中包含一系列Python命令——或者我可以在shell中粘贴相同的命令,它们将执行相同的命令。对于上面这个简单的程序,这是我想要做的(其中C>代表想象的提示符):

C> #include <stdio.h>
(stdio.h included)
C> int a=2;
C> printf("Hello World %d\n", a);
Hello World 2

C> 

In other words, I'd like to be able to execute individual C commands interactively (I'm guessing this would represent on-the-fly compilation of sorts?). Initially I was misled by the name of the C shell (csh) - but I don't think it will be able to execute C commands on the fly.

换句话说,我希望能够交互式地执行单独的C命令(我猜这将代表动态的编译)。最初,我被C shell (csh)的名称误导了——但我认为它不能动态地执行C命令。

So, first and foremost, I'd like to know if it is possible somehow to persuade, say, gdb to perform in this manner? If not, is there anything else that would allow me to do something similar (some special shell, maybe)?

所以,首先,我想知道是否有可能说服gdb这样做?如果没有,还有什么可以让我做一些类似的事情(也许是一些特殊的shell)?

As for the context - I have some code where I have problems troubleshooting pointers between structs and such; here the way gdb can printout structs works very well - however, to isolate the problem, I have to make new source files, paste in data, compile and debug all over again. In this case, I'd much rather have the possibility to paste several structs (and their initialization commands) in some sort of a shell - and then, inspect using printf (or even better, something akin to gdb's print) typed directly on the shell.

至于上下文——我有一些代码,在这些代码中,我对结构之间的指针进行故障排除有问题;在这里,gdb可以打印出struct的方法非常有效——但是,为了隔离问题,我必须重新创建新的源文件,粘贴数据,重新编译和调试。在这种情况下,我更希望能够在某种shell中粘贴几个struct(以及它们的初始化命令)——然后,使用printf(甚至类似于gdb的print)直接在shell中进行检查。

Just for the record - I'm not really persuaded something like this really exists; but I thought I'd ask anyways :)

我并不是真的相信这种东西真的存在;但我还是想问:

Thanks in advance for any answers,
Cheers!  
 

谢谢你的回答,干杯!  

EDIT: I was a bit busy, so haven't had time to review all answers yet for accept (sorry :) ); just wanted to add a little comment re:"interpreted vs. machine code"; or as mentioned by @doron:

编辑:我有点忙,所以还没有时间复习所有的答案接受(抱歉:);只是想添加一点注释re:“解释与机器代码”;或如@doron提及:

The problem with running C /C++ source interactively is that the compiler is not able to perform line by line interpretation of the code.

交互式地运行C / c++源代码的问题是编译器不能逐行地解释代码。

I am fully aware of this - but let's imagine a command line application (could even be an interpreted one), that gives you a prompt with a command line interface. At start, let's assume this application generates this simple "text file" in memory:

我完全清楚这一点——但是让我们假设一个命令行应用程序(甚至可以是一个解释的应用程序),它会给您一个命令行接口的提示符。首先,假设这个应用程序在内存中生成这个简单的“文本文件”:

@@HEADER@@

int main()
{
    @@MAIN@@

    return 0;
} 

Then, the application simply waits for a text to be entered at the prompt, and ENTER to be pressed; and upon a new line:

然后,应用程序只需在提示符处等待输入文本,然后按下ENTER键;在一条新路线上:

  • The application checks:
    • if the line starts with #define or #include, then it is added below the @@HEADER@@ - but above the int main() line - in the temp file
    • 如果一行以#define或#include开头,那么它将添加到temp文件中的@ header@header@@ -但在int main()行之上
    • anything else, goes below @@MAIN@@ line - but above return 0; line - in the temp file
    • 任何其他的,在@@MAIN@@行下面-但是在返回0上面;行-在临时文件中
  • 应用程序检查:如果一行以#define或#include开头,那么它将添加到@ header@header@@ @ -但是在temp文件中的int main()行之上——在@ main@main@include行下面——但是在返回0之上;行-在临时文件中
  • the temp file is stripped of @@HEADER@@ and @@MAIN@@ lines, and saved to disk as temp.c
  • temp文件被删除为@ header@header@@和@@MAIN@@ @ lines,并以temp.c的形式保存到磁盘
  • gcc is called to compile temp.c and generate temp.out executable
    • if fail, notify user, exit
    • 如果失败,通知用户,退出
  • 调用gcc来编译temp.c .并生成temp.out可执行文件,如果失败,通知用户,退出
  • gdb is called to run the temp.out executable, with a breakpoint set at the return 0; line
    • if fail, notify user, exit
    • 如果失败,通知用户,退出
  • 调用gdb来运行temp.out可执行文件,在返回0时设置断点;行如果失败,通知用户,退出
  • execution is returned to the prompt; the next commands the user enters, are in fact passed to gdb (so the user can use commands like p variable to inspect) - until the user presses, say, Ctrl+1 to exit gdb
  • 执行返回到提示符;用户输入的下一个命令实际上被传递给gdb(因此用户可以使用像p变量这样的命令来检查)——直到用户按下Ctrl+1退出gdb
  • Ctrl+1 - gdb exits, control is returned to our application - which waits for the next code line all over again.. etc
    • (subsequent code line entries are kept in the temp file - placed below the last entry from the same category)
    • (随后的代码行条目被保存在临时文件中——置于同一类别的最后一个条目之下)
  • Ctrl+1 - gdb退出,控制返回到我们的应用程序-等待下一个代码行再一次。etc(后面的代码行条目保存在temp文件中——位于同一类别的最后一个条目之下)

Obviously, I wouldn't expect to be able to paste the entire linux kernel code into an application like this, and expect it to work :) However, I would expect to be able to paste in a couple of structs, and to inspect the results of statements like, say:

显然,我不期望能够将整个linux内核代码粘贴到这样的应用程序中,并期望它能够工作:)然而,我希望能够粘贴一些结构,并检查语句的结果,比如:

char dat = (char) (*(int16_t*)(my->structure->pdata) >> 32 & 0xFF) ^ 0x88; 

... so I'm sure in what is the proper syntax to use (which is usually what I mess up with) - without the overhead of rebuilding and debugging the entire software, just to figure out whether I should have moved a right parenthesis before or after the asterisk sign (in the cases when such an action doesn't raise a compilation error, of course).

…所以我相信在使用适当的语法是什么(这通常是我混乱了)——没有重建的开销和调试整个软件,为了弄清楚我应该搬到一个右括号之前或之后星号标志(的情况下当这样一个行动不提高编译错误,当然)。

Now, I'm not sure of the entire scope of problems that can arise from a simplistic application architecture as above. But, it's an example, that simply points that something like a "C shell" (for relatively simple sessions/programs) would be conceptually doable, by also using gcc and gdb - without any serious *es with the, otherwise, strict distinction between 'machine code' and 'interpreted' languages.

现在,我不确定是否会出现上述简单的应用程序架构所带来的全部问题。但是,这只是一个例子,它简单地指出,类似“C shell”(对于相对简单的会话/程序)这样的东西在概念上是可行的,还可以使用gcc和gdb—不会与“机器代码”和“解释语言”有任何严重的冲突。

5 个解决方案

#1


6  

There are C interpreters.
Look for Ch or CINT.

有C解释器。找Ch或CINT。

#2


5  

Edit: found a new (untested) thing that appears to be what the OP wants

编辑:找到一个新的(未经测试的)东西,看起来是OP想要的

c-repl

c-repl

Or just use it [...] like driving a Ferarri on city streets.

或者就用它[……]就像在城市的街道上驾驶一辆法拉利。


Tiny C Compiler

小C编译器

  • [... many features, including]
  • […许多功能,包括)
  • C script supported : just add '#!/usr/local/bin/tcc -run' at the first line of your C source, and execute it directly from the command line.
  • C脚本支持:添加#!在C源的第一行运行/usr/local/bin/tcc -run,并直接从命令行执行它。

#3


1  

When your CPU runs a computer program, it runs something called machine code. This is a series of binary instructions that are specific to the CPU that you are using. Since machine code is quite hard to hand code, people invented higher level languages like C and C++. Unfortunately the CPU only understands machine code. So what happens is that we run a compiler that converts the high-level source language into machine code. Computer languages in this class are compiled language like C and C++. These languages are said to run natively since the generated machine code is run by the CPU without any further interpretation.

当你的CPU运行一个计算机程序时,它运行一个叫做机器代码的东西。这是一组特定于您所使用的CPU的二进制指令。由于机器代码很难手工编写,人们发明了高级语言,如C和c++。不幸的是,CPU只理解机器代码。因此,我们运行的编译器将高级源语言转换成机器码。本类中的计算机语言是编译语言,如C和c++。这些语言据说是本机运行的,因为生成的机器代码是由CPU运行的,没有任何进一步的解释。

Now certain languages like Python, Bash and Perl do not need to be compiled beforehand and are rather interpreted. This means that the source file is read line by line by the interpreter and the correct task for the line is performed. This gives you the ability run stuff in an interactive shell as we see in Python.

现在,某些语言(如Python、Bash和Perl)不需要事先编译,而是需要进行解释。这意味着解释器逐行读取源文件,并执行正确的行任务。这使您能够在交互式shell中运行东西,正如我们在Python中看到的那样。

The problem with running C /C++ source interactively is that the compiler is not able to perform line by line interpretation of the code. It is designed solely to generate corresponding machine code and therefore cannot run your C / C++ source interactively.

运行C / c++源的问题是,编译器不能通过代码的行解释来执行行。它只用于生成相应的机器代码,因此不能交互式地运行您的C / c++源代码。

#4


1  

@buddhabrot and @pmg - thank you for your answers!

@buddhabrot和@pmg -感谢您的回复!

For the benefit of n00bery, here is a summary of the answers (as I couldn't immediately grasp what is going on): what I needed (in OP) is handled by what is called a "C Interpreter" (not a 'C shell'), of which the following were suggested:

为了n00bery的好处,这里有一个答案的总结(因为我不能马上理解发生了什么):我需要的(OP中的)由所谓的“C解释器”(不是“C shell”)来处理,其中建议如下:

  • CINT | ROOT - Ubuntu: install as sudo apt-get install root-system-bin (5.18.00-2.3ubuntu4 + 115MB of additional disk space)
  • CINT | ROOT - Ubuntu:以sudo apt-get方式安装ROOT -system-bin (5.18.00-2.3ubuntu4 + 115MB附加磁盘空间)
  • c-repl (c-repl README)- Ubuntu: install as sudo apt-get install c-repl (c-repl_0.0.20071223-1_i386.deb + 106kB of additional disk space)
  • c-repl Ubuntu(c-repl README):安装sudo apt-get安装c-repl(c-repl_0.0.20071223-1_i386.deb + 106 kb的额外的磁盘空间)
  • Ch standard edition - standard edition is freeware for windows/Unix  
     
  • 标准版是针对windows/Unix的免费软件。

For c-repl - there is a quick tutorial on c-repl homepage as an example session; but here is how the same commands behave on my Ubuntu Lucid system, with the repository version (edit: see Where can I find c-repl documentation? for a better example):

对于c-repl -有一个快速教程在c-repl主页作为一个例子会议;但是在我的ubuntulucid系统和repository版本上,同样的命令是如何运行的(编辑:看看哪里可以找到c-repl文档?)为一个更好的例子):

$ c-repl 
> int x = 3
> ++x
> .p x
unknown command: p
> printf("%d %p\n", x, &x)
4 0xbbd014
> .t fprintf
repl is ok
> #include <unistd.h>
<stdin>:1:22: warning: extra tokens at end of #include directive
> getp
p getp
No symbol "getp" in current context.
> printf("%d\n", getpid())
10284
> [Ctrl+C]
/usr/bin/c-repl:185:in `readline': Interrupt
    from /usr/bin/c-repl:185:in `input_loop'
    from /usr/bin/c-repl:184:in `loop'
    from /usr/bin/c-repl:184:in `input_loop'
    from /usr/bin/c-repl:203

Apparently, it would be best to build c-repl from latest source.  
 

显然,最好从最新的源代码构建c-repl。  

For cint it was a bit difficult to find something relateed to it directly (the webpage refers to ROOT Tutorials instead), but then I found "Le Huy: Using CINT - C/C++ Interpreter - Basic Commands"; and here is an example session from my system:

cint有点难找到直接相关的东西(网页指根教程),但后来我发现“Le Huy:使用cint - C / c++翻译基本命令”;这里是一个例子会话从我的系统:

(Note: if cint is not available on your distribution's package root-system-bin, try root instead.)

(注意:如果您的发行版的包root-system-bin上没有cint,请尝试root。)

$ cint

cint : C/C++ interpreter  (mailing list 'cint@root.cern.ch')
   Copyright(c) : 1995~2005 Masaharu Goto (gotom@hanno.jp)
   revision     : 5.16.29, Jan 08, 2008 by M.Goto

No main() function found in given source file. Interactive interface started.
'?':help, '.q':quit, 'statement','{statements;}' or '.p [expr]' to evaluate

cint> L iostream
Error: Symbol Liostream is not defined in current scope  (tmpfile):1:
*** Interpreter error recovered ***
cint> {#include <iostream>}
cint> files
Error: Symbol files is not defined in current scope  (tmpfile):1:
*** Interpreter error recovered ***
cint> {int x=3;}
cint> {++x}
Syntax Error: ++x Maybe missing ';' (tmpfile):2:
*** Interpreter error recovered ***
cint> {++x;}
(int)4
cint> .p x
(int)4
cint> printf("%d %p\n", x, &x)
4 0x8d57720
(const int)12
cint> printf("%d\n", getpid())
Error: Function getpid() is not defined in current scope  (tmpfile):1:
*** Interpreter error recovered ***
cint> {#include <unistd.h>}
cint> printf("%d\n", getpid())
10535
(const int)6
cint> .q
  Bye... (try 'qqq' if still running)

In any case, that is exactly what I needed: ability to load headers, add variables, and inspect the memory they will take! Thanks again, everyone - Cheers!

无论如何,这正是我所需要的:能够加载header、添加变量并检查它们将占用的内存!再次谢谢大家,干杯!

#5


0  

Python and c belongs to different kinds of language. Python is interpreted line by line when running, but c should compile, link and generate code to run.

Python和c属于不同类型的语言。Python在运行时是逐行解释的,但是c应该编译、链接并生成要运行的代码。

#1


6  

There are C interpreters.
Look for Ch or CINT.

有C解释器。找Ch或CINT。

#2


5  

Edit: found a new (untested) thing that appears to be what the OP wants

编辑:找到一个新的(未经测试的)东西,看起来是OP想要的

c-repl

c-repl

Or just use it [...] like driving a Ferarri on city streets.

或者就用它[……]就像在城市的街道上驾驶一辆法拉利。


Tiny C Compiler

小C编译器

  • [... many features, including]
  • […许多功能,包括)
  • C script supported : just add '#!/usr/local/bin/tcc -run' at the first line of your C source, and execute it directly from the command line.
  • C脚本支持:添加#!在C源的第一行运行/usr/local/bin/tcc -run,并直接从命令行执行它。

#3


1  

When your CPU runs a computer program, it runs something called machine code. This is a series of binary instructions that are specific to the CPU that you are using. Since machine code is quite hard to hand code, people invented higher level languages like C and C++. Unfortunately the CPU only understands machine code. So what happens is that we run a compiler that converts the high-level source language into machine code. Computer languages in this class are compiled language like C and C++. These languages are said to run natively since the generated machine code is run by the CPU without any further interpretation.

当你的CPU运行一个计算机程序时,它运行一个叫做机器代码的东西。这是一组特定于您所使用的CPU的二进制指令。由于机器代码很难手工编写,人们发明了高级语言,如C和c++。不幸的是,CPU只理解机器代码。因此,我们运行的编译器将高级源语言转换成机器码。本类中的计算机语言是编译语言,如C和c++。这些语言据说是本机运行的,因为生成的机器代码是由CPU运行的,没有任何进一步的解释。

Now certain languages like Python, Bash and Perl do not need to be compiled beforehand and are rather interpreted. This means that the source file is read line by line by the interpreter and the correct task for the line is performed. This gives you the ability run stuff in an interactive shell as we see in Python.

现在,某些语言(如Python、Bash和Perl)不需要事先编译,而是需要进行解释。这意味着解释器逐行读取源文件,并执行正确的行任务。这使您能够在交互式shell中运行东西,正如我们在Python中看到的那样。

The problem with running C /C++ source interactively is that the compiler is not able to perform line by line interpretation of the code. It is designed solely to generate corresponding machine code and therefore cannot run your C / C++ source interactively.

运行C / c++源的问题是,编译器不能通过代码的行解释来执行行。它只用于生成相应的机器代码,因此不能交互式地运行您的C / c++源代码。

#4


1  

@buddhabrot and @pmg - thank you for your answers!

@buddhabrot和@pmg -感谢您的回复!

For the benefit of n00bery, here is a summary of the answers (as I couldn't immediately grasp what is going on): what I needed (in OP) is handled by what is called a "C Interpreter" (not a 'C shell'), of which the following were suggested:

为了n00bery的好处,这里有一个答案的总结(因为我不能马上理解发生了什么):我需要的(OP中的)由所谓的“C解释器”(不是“C shell”)来处理,其中建议如下:

  • CINT | ROOT - Ubuntu: install as sudo apt-get install root-system-bin (5.18.00-2.3ubuntu4 + 115MB of additional disk space)
  • CINT | ROOT - Ubuntu:以sudo apt-get方式安装ROOT -system-bin (5.18.00-2.3ubuntu4 + 115MB附加磁盘空间)
  • c-repl (c-repl README)- Ubuntu: install as sudo apt-get install c-repl (c-repl_0.0.20071223-1_i386.deb + 106kB of additional disk space)
  • c-repl Ubuntu(c-repl README):安装sudo apt-get安装c-repl(c-repl_0.0.20071223-1_i386.deb + 106 kb的额外的磁盘空间)
  • Ch standard edition - standard edition is freeware for windows/Unix  
     
  • 标准版是针对windows/Unix的免费软件。

For c-repl - there is a quick tutorial on c-repl homepage as an example session; but here is how the same commands behave on my Ubuntu Lucid system, with the repository version (edit: see Where can I find c-repl documentation? for a better example):

对于c-repl -有一个快速教程在c-repl主页作为一个例子会议;但是在我的ubuntulucid系统和repository版本上,同样的命令是如何运行的(编辑:看看哪里可以找到c-repl文档?)为一个更好的例子):

$ c-repl 
> int x = 3
> ++x
> .p x
unknown command: p
> printf("%d %p\n", x, &x)
4 0xbbd014
> .t fprintf
repl is ok
> #include <unistd.h>
<stdin>:1:22: warning: extra tokens at end of #include directive
> getp
p getp
No symbol "getp" in current context.
> printf("%d\n", getpid())
10284
> [Ctrl+C]
/usr/bin/c-repl:185:in `readline': Interrupt
    from /usr/bin/c-repl:185:in `input_loop'
    from /usr/bin/c-repl:184:in `loop'
    from /usr/bin/c-repl:184:in `input_loop'
    from /usr/bin/c-repl:203

Apparently, it would be best to build c-repl from latest source.  
 

显然,最好从最新的源代码构建c-repl。  

For cint it was a bit difficult to find something relateed to it directly (the webpage refers to ROOT Tutorials instead), but then I found "Le Huy: Using CINT - C/C++ Interpreter - Basic Commands"; and here is an example session from my system:

cint有点难找到直接相关的东西(网页指根教程),但后来我发现“Le Huy:使用cint - C / c++翻译基本命令”;这里是一个例子会话从我的系统:

(Note: if cint is not available on your distribution's package root-system-bin, try root instead.)

(注意:如果您的发行版的包root-system-bin上没有cint,请尝试root。)

$ cint

cint : C/C++ interpreter  (mailing list 'cint@root.cern.ch')
   Copyright(c) : 1995~2005 Masaharu Goto (gotom@hanno.jp)
   revision     : 5.16.29, Jan 08, 2008 by M.Goto

No main() function found in given source file. Interactive interface started.
'?':help, '.q':quit, 'statement','{statements;}' or '.p [expr]' to evaluate

cint> L iostream
Error: Symbol Liostream is not defined in current scope  (tmpfile):1:
*** Interpreter error recovered ***
cint> {#include <iostream>}
cint> files
Error: Symbol files is not defined in current scope  (tmpfile):1:
*** Interpreter error recovered ***
cint> {int x=3;}
cint> {++x}
Syntax Error: ++x Maybe missing ';' (tmpfile):2:
*** Interpreter error recovered ***
cint> {++x;}
(int)4
cint> .p x
(int)4
cint> printf("%d %p\n", x, &x)
4 0x8d57720
(const int)12
cint> printf("%d\n", getpid())
Error: Function getpid() is not defined in current scope  (tmpfile):1:
*** Interpreter error recovered ***
cint> {#include <unistd.h>}
cint> printf("%d\n", getpid())
10535
(const int)6
cint> .q
  Bye... (try 'qqq' if still running)

In any case, that is exactly what I needed: ability to load headers, add variables, and inspect the memory they will take! Thanks again, everyone - Cheers!

无论如何,这正是我所需要的:能够加载header、添加变量并检查它们将占用的内存!再次谢谢大家,干杯!

#5


0  

Python and c belongs to different kinds of language. Python is interpreted line by line when running, but c should compile, link and generate code to run.

Python和c属于不同类型的语言。Python在运行时是逐行解释的,但是c应该编译、链接并生成要运行的代码。