0

Is there any conceptual limitation that would make impossible to create a C program line by line as in 'Mathematica notebooks'[1]?

[1] One key aspect of Mathematica is that you can create your code line by line in a format called 'notebook'. This makes it much easier to debug the code during the development phase. After most of the code has been developed and debugged, is just a matter of copy and paste your code from the notebook format to a batch format (currently it's not possible to compile Mathematica codes).

  • 1
    run line by line or write line by line? – ratchet freak Nov 20 '15 at 15:01
  • Good point. The latter one: write your C code line by line on the fly as in Mathematica. – Mark Messa Nov 20 '15 at 15:06
  • 1
    I think the OP might be asking about a REPL for C. I'm not sure I understand the question, though. – Andres F. Nov 20 '15 at 15:35
  • 7
    Related on SO: Is there a REPL for C programming? (a repl is a read–eval–print loop that many programming environments provide - not all) – user40980 Nov 20 '15 at 16:05
  • 1
    Perhaps your real question could be: "Is coding in C as easy as coding Mathematica"? The answer is no and it not a matter of tools but of semantics of the C programming language. – Basile Starynkevitch Nov 20 '15 at 17:56
7

In practice, compile your C code with all warnings and debug info (e.g. gcc -Wall -Wextra -g if using GCC...) then use a debugger (such as GDB).

With a debugger you can run your C code line by line. For gdb use the step and/or next commands.

Once you are sure there is almost no bugs in your code, and no simple bug, you'll compile with gcc -Wall -Wextra -march=native -O2 -g to get a production executable (don't forget to test it too!) and/or for benchmarking purposes.

You could use a good editor such as emacs and configure it to compile your code with one key, and start the debugger with another key.

BTW, several language implementations are able to compile on the fly to machine code, in particular the SBCL implementation of Common Lisp.

On some systems (in particular Linux), you could write a program which generates at runtime some C code in a temporary file /tmp/mytemp.c, compile that file as a plugin (by forking a gcc -Wall -shared -O -fPIC /tmp/mytemp.c -o /tmp/mytemp.so command), dynamically load that plugin (dlopen(3)), find function pointers from its name inside it (dlsym(3)) and run these functions (in the same process that generated their C source code). My GCC MELT tool (free software, GPLv3) is doing this. In practice compilers are fast enough to make that usable for interactive purposes.

It could be difficult to write C code line by line, since C is not a line oriented language (most newlines -outside of macro definitions- in C are understood by the compiler as a space). Actually a C compiler handles only translation units (which you could generate in some /tmp/mytemp.c file).

But you could, in your program, read some lines, pack them inside a function source, emit that generated C code in a temporary file, and compile and load that as a plugin as I explained above (system on the compilation command building the plugin, dlopen + dlsym on the plugin).

(Of course, some undefined behavior inside the generated plugin would often crash the entire process, so in practice it would be better to generate the plugin C code from something higher level, and be sure that the generated C code is reasonably correct and won't crash.)

Of course, it uses operating system features: dynamic loading with dlopen is standardized by POSIX (and the command to compile a plugin is often OS specific), not by C99.

You might instead consider embedding some interpreter like Guile or Lua in your program. Or perhaps consider a JIT compiling approach, using libraries like libjit, asmjit, GCCJIT, LLVM, etc....

I am not saying that C (in its usual implementations) has any Read Eval Print Loop (like Common Lisp has). It does not (see this, as commented by MichaelT). And a REPL implementation might not reproduce faithfully the undefined behavior and faults (segmentation violation ...) that a compiled program has.

If you code in C (in particular on Linux, which I recommend), you'll use several tools (sometimes branded in some IDE combining them): an editor (emacs), a version control system (git), a builder (GNU make, see my hints here) which would run the gcc compiler etc etc, a debugger (gdb), and others (etags, grep, valgrind...). With some habit, you'll be very productive by using them together. And since your translation units will remain small (no more than a few thousand lines per source file), compilation is going fast today (less than a few seconds), unless you work on some huge free software project (like the GCC compiler, the Linux kernel, the Mozilla browser in C++, ...) of many millions of source code lines. But trying to contribute to huge project without any prior C experience is insane; so start with your own small C project (two dozens of thousands lines would require you a full year of work).

Since compilation is quick -typically less than a couple of seconds- you can afford compiling very often (e.g. several times each minute) and run your current test in the debugger; in rare cases -huge projects like GCC or the Linux kernel, compilation is much slower, but you won't be in that case without being very experimented in C coding, and then you'll have developed your own skills, tips and tricks to overcome the slowness of the build. So just be sure that your project is compiled quickly: use several translation units, so don't have source files bigger than a few thousand lines each, and master some builder (e.g. have a good Makefile for GNU make). Hence a REPL for C is practically useless, the compiler is fast enough ... Configure your editor, e.g. emacs, to be able to rebuild your program at a keystroke in a few seconds at most (perhaps with a parallel build, à la make -j).


Notice that coding in C is hard, probably much harder than coding in Mathematica, not because of tools deficiency, but intrinsically because the semantics of C99 is difficult to master (notably, you'll need to understand precisely the potential undefined behavior and know how the computer works). Even with the right tools you'll spend days or weeks hunting some of your bugs; and it is not a matter of syntax (the syntax of C99 is relatively simple).

IMHO, it is the semantics of C99 which makes it hard to learn, and which makes REPL implementations of C rather useless. In practice, you won't be slowed by the compilation time (probably a second or two for you, if you are working on a fresh project), so you practically won't need any REPL. But you'll experiment that coding in C is difficult (but you'll learn a lot)

  • 1) My fault, I should have written 'write C line by line' instead of 'run C line by line' – Mark Messa Nov 20 '15 at 15:11
  • 2) Ok, it seems that there are some intrinsic characteristics in C that would undermine writing a code line by line as you can in Mathematica notebooks – Mark Messa Nov 20 '15 at 15:16
  • @MarkMessa: it is not mostly a characteristic of C (whose syntax is indeed not line-oriented, but block-oriented), but also of the operating system. In particular, dlopen does not exist on Windows (which I don't know). – Basile Starynkevitch Nov 20 '15 at 15:17
  • Ok, I think I understand your point. The syntax of Mathematica also is not line-oriented, instead is functional oriented. In Mathematica you also can't develop your code 'line-by-line', but you can develop it block by block (function oriented). – Mark Messa Nov 20 '15 at 15:23
  • 1
    No, I am a big fan of Lisp & Ocaml (and I prefer generated C than hand-written C) and of REPL. The point is that the semantics of C is difficult (much harder than Scheme: I taught semantics of Scheme at university -Master's level- but teaching the entire semantics of C would be much harder...). And I am not sure that REPL is better than compilation: in Ocaml, you have both, and I rarely use REPL – Basile Starynkevitch Nov 20 '15 at 19:02
4

There is an open source project called Jupyter that is basically a notebook-like format like mathematica with many pluggable kernels that support various languages on the back end. C++ is listed as one of the kernels, using the Cling REPL. So, yes. It's not only possible, it's been done.

Granted, C++ is not precisely C, but it's close enough to prove the concept. Also, I wouldn't really call it writing a program. It's more suited for the kinds of things you do with mathematica: presenting code snippets together with formatted text and graphics.

I haven't personally used the C++ backend, but together with the RISE extension, jupyter made for a very effective presentation tool for a programming tech talk I taught in Scala. When people have questions about the code, you can make changes and show its effect on the fly, without leaving your presentation.

I wouldn't use it for day-to-day development work, though. I think most C programmers who like the rapid feedback of a REPL have adopted processes like test driven development, which actually avoids your copy and paste step.

  • Ok, seems to be a nice REPL for C++. I'm wondering why most C programmers avoid REPL for rapid feedback while Mathematica's users enjoy it a lot. Later I'll post this as another topic ... – Mark Messa Nov 21 '15 at 0:15

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.