Run C or C++ file as a script

2020-02-07 17:56发布

So this is probably a long shot, but is there any way to run a C or C++ file as a script? I tried:

#!/usr/bin/gcc main.c -o main; ./main

int main(){ return 0; }

But it says:

./main.c:1:2: error: invalid preprocessing directive #!

标签: c++ c shell
12条回答
不美不萌又怎样
2楼-- · 2020-02-07 18:02
$ cat /usr/local/bin/runc
#!/bin/bash
sed -n '2,$p' "$@" | gcc -o /tmp/a.out -x c++ - && /tmp/a.out
rm -f /tmp/a.out

$ cat main.c
#!/bin/bash /usr/local/bin/runc

#include <stdio.h>

int main() {
    printf("hello world!\n");
    return 0;
}

$ ./main.c
hello world!

The sed command takes the .c file and strips off the hash-bang line. 2,$p means print lines 2 to end of file; "$@" expands to the command-line arguments to the runc script, i.e. "main.c".

sed's output is piped to gcc. Passing - to gcc tells it to read from stdin, and when you do that you also have to specify the source language with -x since it has no file name to guess from.

查看更多
女痞
3楼-- · 2020-02-07 18:07

Quite a short proposal would exploit:

  • The current shell script being the default interpreter for unknown types (without a shebang or a recognizable binary header).
  • The "#" being a comment in shell and "#if 0" disabling code.

    #if 0
    F="$(dirname $0)/.$(basename $0).bin"
    [ ! -f $F  -o  $F -ot $0 ] && { c++ "$0" -o "$F" || exit 1 ; }
    exec "$F" "$@"
    #endif
    
    // Here starts my C++ program :)
    #include <iostream>
    #include <unistd.h>
    
    using namespace std;
    
    int main(int argc, char **argv) {
        if (argv[1])
             clog << "Hello " << argv[1] << endl;
        else
            clog << "hello world" << endl;
    }
    

Then you can chmod +x your .cpp files and then ./run.cpp.

  • You could easily give flags for the compiler.
  • The binary is cached in the current directory along with the source, and updated when necessary.
  • The original arguments are passed to the binary: ./run.cpp Hi
  • It doesn't reuse the a.out, so that you can have multiple binaries in the same folder.
  • Uses whatever c++ compiler you have in your system.
  • The binary starts with "." so that it is hidden from the directory listing.

Problems:

  • What happens on concurrent executions?
查看更多
唯我独甜
4楼-- · 2020-02-07 18:10

You might want to checkout ryanmjacobs/c which was designed for this in mind. It acts as a wrapper around your favorite compiler.

#!/usr/bin/c
#include <stdio.h>

int main(void) {
    printf("Hello World!\n");
    return 0;
}

The nice thing about using c is that you can choose what compiler you want to use, e.g.

$ export CC=clang
$ export CC=gcc

So you get all of your favorite optimizations too! Beat that tcc -run!

You can also add compiler flags to the shebang, as long as they are terminated with the -- characters:

#!/usr/bin/c -Wall -g -lncurses --
#include <ncurses.h>

int main(void) {
    initscr();
    /* ... */
    return 0;
}

c also uses $CFLAGS and $CPPFLAGS if they are set as well.

查看更多
The star\"
5楼-- · 2020-02-07 18:13

CINT:

CINT is an interpreter for C and C++ code. It is useful e.g. for situations where rapid development is more important than execution time. Using an interpreter the compile and link cycle is dramatically reduced facilitating rapid development. CINT makes C/C++ programming enjoyable even for part-time programmers.

查看更多
够拽才男人
6楼-- · 2020-02-07 18:13

Here's yet another alternative:

#if 0
TMP=$(mktemp -d)
cc -o ${TMP}/a.out ${0} && ${TMP}/a.out ${@:1} ; RV=${?}
rm -rf ${TMP}
exit ${RV}
#endif

#include <stdio.h>

int main(int argc, char *argv[])
{
  printf("Hello world\n");
  return 0;
}
查看更多
家丑人穷心不美
7楼-- · 2020-02-07 18:15

For C, you may have a look at tcc, the Tiny C Compiler. Running C code as a script is one of its possible uses.

查看更多
登录 后发表回答