Run C or C++ file as a scriptHow can I prevent gcc from pre-processing a shebang line?Is there an interpreter for C?Have you used any of the C++ interpreters (not compilers)?Are there any low-level languages that can be used in place of scripts?Execute Code Written in a jtextareaWhat are the differences between a pointer variable and a reference variable in C++?Check if a directory exists in a shell scriptHow to use SSH to run a shell script on a remote machine?Why does C++ compilation take so long?How can I profile C++ code running on Linux?The Definitive C++ Book Guide and ListHow to mkdir only if a dir does not already exist?What is the effect of extern “C” in C++?What is the “-->” operator in C++?Compiling an application for use in highly radioactive environments

Multi tool use
Greek theta instead of lower case þ (Icelandic) in TexStudio
Should I twist DC power and ground wires from a power supply?
Is it possible to view all the attribute data in QGIS
Was Tyrion always a poor strategist?
What does this 'x' mean on the stem of the voice's note, above the notehead?
Behavior of __LINE__ when used in a macro
Managing heat dissipation in a magic wand
Warped chessboard
Character had a different name in the past. Which name should I use in a flashback?
In How Many Ways Can We Partition a Set Into Smaller Subsets So The Sum of the Numbers In Each Subset Is Equal?
Can a problematic AL DM/organizer prevent me from running a separatate AL-legal game at the same store?
pwaS eht tirsf dna tasl setterl fo hace dorw
Bash Read: Reading comma separated list, last element is missed
Why does string strummed with finger sound different from the one strummed with pick?
Are there any crystals that are theoretically possible, but haven't yet been made?
Why is python script running in background consuming 100 % CPU?
Better than Rembrandt
Would it be possible to set up a franchise in the ancient world?
How to safely discharge oneself
Does ratifying USMCA imply a (stealth) ratification of UNCLOS?
Can a Warforged have a ranged weapon affixed to them like an armblade?
How can I stop my kitten from growing?
Germany rejected my entry to Schengen countries
On a piano, are the effects of holding notes and the sustain pedal the same for a single chord?
Run C or C++ file as a script
How can I prevent gcc from pre-processing a shebang line?Is there an interpreter for C?Have you used any of the C++ interpreters (not compilers)?Are there any low-level languages that can be used in place of scripts?Execute Code Written in a jtextareaWhat are the differences between a pointer variable and a reference variable in C++?Check if a directory exists in a shell scriptHow to use SSH to run a shell script on a remote machine?Why does C++ compilation take so long?How can I profile C++ code running on Linux?The Definitive C++ Book Guide and ListHow to mkdir only if a dir does not already exist?What is the effect of extern “C” in C++?What is the “-->” operator in C++?Compiling an application for use in highly radioactive environments
.everyoneloves__top-leaderboard:empty,.everyoneloves__mid-leaderboard:empty,.everyoneloves__bot-mid-leaderboard:empty height:90px;width:728px;box-sizing:border-box;
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
add a comment |
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
3
There are interpreters: cint, ch; plus igcc and tcc will act like one. There are some questions about them around here somewhere: stackoverflow.com/questions/69539/… stackoverflow.com/questions/584714/… and probably a few others. And this may be a duplicate: stackoverflow.com/questions/2277865/…
– dmckee
Mar 20 '10 at 8:15
add a comment |
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
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
c++ c shell
asked Mar 20 '10 at 7:48
Brendan LongBrendan Long
40.7k12115156
40.7k12115156
3
There are interpreters: cint, ch; plus igcc and tcc will act like one. There are some questions about them around here somewhere: stackoverflow.com/questions/69539/… stackoverflow.com/questions/584714/… and probably a few others. And this may be a duplicate: stackoverflow.com/questions/2277865/…
– dmckee
Mar 20 '10 at 8:15
add a comment |
3
There are interpreters: cint, ch; plus igcc and tcc will act like one. There are some questions about them around here somewhere: stackoverflow.com/questions/69539/… stackoverflow.com/questions/584714/… and probably a few others. And this may be a duplicate: stackoverflow.com/questions/2277865/…
– dmckee
Mar 20 '10 at 8:15
3
3
There are interpreters: cint, ch; plus igcc and tcc will act like one. There are some questions about them around here somewhere: stackoverflow.com/questions/69539/… stackoverflow.com/questions/584714/… and probably a few others. And this may be a duplicate: stackoverflow.com/questions/2277865/…
– dmckee
Mar 20 '10 at 8:15
There are interpreters: cint, ch; plus igcc and tcc will act like one. There are some questions about them around here somewhere: stackoverflow.com/questions/69539/… stackoverflow.com/questions/584714/… and probably a few others. And this may be a duplicate: stackoverflow.com/questions/2277865/…
– dmckee
Mar 20 '10 at 8:15
add a comment |
10 Answers
10
active
oldest
votes
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.
3
Oh I like this one. All you have to do is add#!/usr/bin/tcc -run
– Brendan Long
Mar 20 '10 at 8:04
1
@Brendan: I'm also quite fond of tcc, especially with regards to compile times; you'll have to beware of compiler-bugs, though
– Christoph
Mar 20 '10 at 8:34
add a comment |
Short answer:
//usr/bin/clang "$0" && exec ./a.out "$@"
int main()
return 0;
The trick is that your text file must be both valid C/C++ code and shell script. Remember to exit
from the shell script before the interpreter reaches the C/C++ code, or invoke exec
magic.
Run with chmod +x main.c; ./main.c
.
A shebang like #!/usr/bin/tcc -run
isn't needed because unix-like systems will already execute the text file within the shell.
(adapted from this comment)
I used it in my C++ script:
//usr/bin/clang++ -O3 -std=c++11 "$0" && ./a.out; exit
#include <iostream>
int main()
for (auto i: 1, 2, 3)
std::cout << i << std::endl;
return 0;
If your compilation line grows too much you can use the preprocessor (adapted from this answer) as this plain old C code shows:
#if 0
clang "$0" && ./a.out
rm -f ./a.out
exit
#endif
int main()
return 0;
Of course you can cache the executable:
#if 0
EXEC=$0%.*
test -x "$EXEC" || clang "$0" -o "$EXEC"
exec "$EXEC"
#endif
int main()
return 0;
Now, for the truly eccentric Java developer:
/*/../bin/true
CLASS_NAME=$(basename "$0%.*")
CLASS_PATH="$(dirname "$0")"
javac "$0" && java -cp "$CLASS_PATH" $CLASS_NAME
rm -f "$CLASS_PATH/$CLASS_NAME.class"
exit
*/
class Main
public static void main(String[] args)
return;
D programmers simply put a shebang at the beginning of text file without breaking the syntax:
#!/usr/bin/rdmd
void main()
Sorry for the rollback.
– Pedro Lacerda
Apr 20 '15 at 16:28
1
to pass arguments to executable c++ code, add "$@" after ./a.out;So it would be -------------------------------- //usr/bin/clang++ -O3 -std=c++11 "$0" && ./a.out "$@"; exit
– scinart
Nov 1 '17 at 7:12
thank you @scinart
– Pedro Lacerda
Nov 1 '17 at 13:15
1
Great answer. I would just also check that the existing binary is not outdated.
– Raúl Salinas-Monteagudo
Nov 22 '18 at 13:06
@RaúlSalinas-Monteagudo in the example 4 it can happen indeed, anstat -c %y a.out main.c
comparison would ameliorate. Somewhat between 1 and 2 looks production ready, lol.
– Pedro Lacerda
Feb 21 at 14:32
add a comment |
$ 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.
I get lots of ld errors with this one :
– Brendan Long
Mar 20 '10 at 8:20
@John Kugelman: What is th need for putting#!/bin/bash /usr/local/bin/runc
as the first line inmain.c
when you are going to strip it usingsed
anyways?
– Lazer
Mar 21 '10 at 2:51
@eSKay - That line tells the system what program to use to "run" the script. Without it bash will try to interpret the.c
file as a bash script and bomb out with a syntax error.
– John Kugelman
Mar 21 '10 at 18:59
@John Kugelman: thanks! I get the complete idea now. very clever!
– Lazer
Mar 21 '10 at 19:09
1
You should use mktemp instead of a.out otherwise you get problems when running two different C-scripts at the same time... Also, the C-script doesn't compile as a real C program because of the hashbang at the top, though I'm not sure what you can do about that...
– Graham
Sep 26 '10 at 12:49
|
show 4 more comments
Since the shebang line will be passed to the compiler, and # indicates a preprocessor directive, it will choke on a #!.
What you can do is embed the makefile in the .c file (as discussed in this xkcd thread)
#if 0
make $@ -f - <<EOF
all: foo
foo.o:
cc -c -o foo.o -DFOO_C $0
bar.o:
cc -c -o bar.o -DBAR_C $0
foo: foo.o bar.o
cc -o foo foo.o bar.o
EOF
exit;
#endif
#ifdef FOO_C
#include <stdlib.h>
extern void bar();
int main(int argc, char* argv[])
bar();
return EXIT_SUCCESS;
#endif
#ifdef BAR_C
void bar()
puts("bar!");
#endif
The #if 0 #endif
pair surrounding the makefile ensure the preprocessor ignores that section of text, and the EOF marker marks where the make command should stop parsing input.
1
Not what I was looking for, but close, and definitely entertaining.
– Brendan Long
Mar 20 '10 at 23:08
add a comment |
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.
Interesting. I'm hoping for something that would have the same result as gcc $stuff; ./filename though. This is already more than I was expecting though.
– Brendan Long
Mar 20 '10 at 7:52
Brendan - If you want to do that you are going to have to write a script in bash or such to compile and call the program.
– zellio
Mar 20 '10 at 7:53
@Brendan: why do you need this, really? To me it doesn't make much sense using C and C++ this way
– Eli Bendersky
Mar 20 '10 at 7:56
No real need, I was just wondering. It would be a funny way to distribute a program.
– Brendan Long
Mar 20 '10 at 8:00
add a comment |
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.
Note that an anonymous suggested edit claims: "It now supports caching. After running a script once, the second time will be practically instant."
– Brock Adams
Jan 1 '16 at 5:04
add a comment |
#!/usr/bin/env sh
tail -n +$(( $LINENO + 1 )) "$0" | cc -xc - && ./a.out "$@"; e="$?"; rm ./a.out; exit "$e";
#include <stdio.h>
int main(int argc, char const* argv[])
printf("Hello world!n");
return 0;
This properly forwards the arguments and the exit code too.
add a comment |
Variatn of John Kugelman can be written in this way:
#!/bin/bash
t=`mktemp`
sed '1,/^//code/d' "$0" | g++ -o "$t" -x c++ - && "$t" "$@"
r=$?
rm -f "$t"
exit $r
//code
#include <stdio.h>
int main()
printf("Hin");
return 0;
This is more than a variation. its a single file implementation and looks nice. The main problem I have with it is that if you load it in a C++ IDE, it will go berserk. you can't hide the shebang, but if you add: /*
after the shebang and#*/
after theexit
command, then the IDE will ignore all the other bash stuff.
– Guss
Dec 19 '16 at 12:55
@Guss, having shebang look like#!/bin/bash : /*
results in error looking for a file: /*
because command line now will look as/bin/bash : /* ./man.c
. Moreover I believe some IDE will report failure for inproper pre-processor instruction#!/bin/bash ...
.
– ony
Dec 20 '16 at 17:53
sorry for not being clear enough in my comment. I meant adding: /*
as the following line after the shebang line. Regarding IDEs not liking the shebang (or the next line that start with:
- yes, probably. The IDEs I normally use mark these as errors but don't make a fuss other than that and the rest of the file is parsed correctly.
– Guss
Dec 21 '16 at 13:54
@Guss, true. That will mark most of the bash code as a comment. Use of#if 0
and#endif
as suggested by @Ephphatha will work also.
– ony
Dec 22 '16 at 15:49
True, but then there's no point in hiding the shell code from the compiler as you do with thesed
expression - you can just give gcc the entire file (minus the shebang). The header then might look like this (note the "n"s in the text, comments are not line oriented):#!/bin/bashn#if 0n t=$(mktemp -u);g++ -o $t -x c++ <(tail -n+2 $0) && $t "$@"; r=$?; rm -f $t; exit $rn#endif
– Guss
Dec 24 '16 at 13:44
|
show 1 more comment
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 ] &&
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?
add a comment |
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 worldn");
return 0;
add a comment |
Your Answer
StackExchange.ifUsing("editor", function ()
StackExchange.using("externalEditor", function ()
StackExchange.using("snippets", function ()
StackExchange.snippets.init();
);
);
, "code-snippets");
StackExchange.ready(function()
var channelOptions =
tags: "".split(" "),
id: "1"
;
initTagRenderer("".split(" "), "".split(" "), channelOptions);
StackExchange.using("externalEditor", function()
// Have to fire editor after snippets, if snippets enabled
if (StackExchange.settings.snippets.snippetsEnabled)
StackExchange.using("snippets", function()
createEditor();
);
else
createEditor();
);
function createEditor()
StackExchange.prepareEditor(
heartbeatType: 'answer',
autoActivateHeartbeat: false,
convertImagesToLinks: true,
noModals: true,
showLowRepImageUploadWarning: true,
reputationToPostImages: 10,
bindNavPrevention: true,
postfix: "",
imageUploader:
brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
allowUrls: true
,
onDemand: true,
discardSelector: ".discard-answer"
,immediatelyShowMarkdownHelp:true
);
);
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
StackExchange.ready(
function ()
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f2482348%2frun-c-or-c-file-as-a-script%23new-answer', 'question_page');
);
Post as a guest
Required, but never shown
10 Answers
10
active
oldest
votes
10 Answers
10
active
oldest
votes
active
oldest
votes
active
oldest
votes
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.
3
Oh I like this one. All you have to do is add#!/usr/bin/tcc -run
– Brendan Long
Mar 20 '10 at 8:04
1
@Brendan: I'm also quite fond of tcc, especially with regards to compile times; you'll have to beware of compiler-bugs, though
– Christoph
Mar 20 '10 at 8:34
add a comment |
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.
3
Oh I like this one. All you have to do is add#!/usr/bin/tcc -run
– Brendan Long
Mar 20 '10 at 8:04
1
@Brendan: I'm also quite fond of tcc, especially with regards to compile times; you'll have to beware of compiler-bugs, though
– Christoph
Mar 20 '10 at 8:34
add a comment |
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.
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.
answered Mar 20 '10 at 7:55


Remo.DRemo.D
13.7k53866
13.7k53866
3
Oh I like this one. All you have to do is add#!/usr/bin/tcc -run
– Brendan Long
Mar 20 '10 at 8:04
1
@Brendan: I'm also quite fond of tcc, especially with regards to compile times; you'll have to beware of compiler-bugs, though
– Christoph
Mar 20 '10 at 8:34
add a comment |
3
Oh I like this one. All you have to do is add#!/usr/bin/tcc -run
– Brendan Long
Mar 20 '10 at 8:04
1
@Brendan: I'm also quite fond of tcc, especially with regards to compile times; you'll have to beware of compiler-bugs, though
– Christoph
Mar 20 '10 at 8:34
3
3
Oh I like this one. All you have to do is add
#!/usr/bin/tcc -run
– Brendan Long
Mar 20 '10 at 8:04
Oh I like this one. All you have to do is add
#!/usr/bin/tcc -run
– Brendan Long
Mar 20 '10 at 8:04
1
1
@Brendan: I'm also quite fond of tcc, especially with regards to compile times; you'll have to beware of compiler-bugs, though
– Christoph
Mar 20 '10 at 8:34
@Brendan: I'm also quite fond of tcc, especially with regards to compile times; you'll have to beware of compiler-bugs, though
– Christoph
Mar 20 '10 at 8:34
add a comment |
Short answer:
//usr/bin/clang "$0" && exec ./a.out "$@"
int main()
return 0;
The trick is that your text file must be both valid C/C++ code and shell script. Remember to exit
from the shell script before the interpreter reaches the C/C++ code, or invoke exec
magic.
Run with chmod +x main.c; ./main.c
.
A shebang like #!/usr/bin/tcc -run
isn't needed because unix-like systems will already execute the text file within the shell.
(adapted from this comment)
I used it in my C++ script:
//usr/bin/clang++ -O3 -std=c++11 "$0" && ./a.out; exit
#include <iostream>
int main()
for (auto i: 1, 2, 3)
std::cout << i << std::endl;
return 0;
If your compilation line grows too much you can use the preprocessor (adapted from this answer) as this plain old C code shows:
#if 0
clang "$0" && ./a.out
rm -f ./a.out
exit
#endif
int main()
return 0;
Of course you can cache the executable:
#if 0
EXEC=$0%.*
test -x "$EXEC" || clang "$0" -o "$EXEC"
exec "$EXEC"
#endif
int main()
return 0;
Now, for the truly eccentric Java developer:
/*/../bin/true
CLASS_NAME=$(basename "$0%.*")
CLASS_PATH="$(dirname "$0")"
javac "$0" && java -cp "$CLASS_PATH" $CLASS_NAME
rm -f "$CLASS_PATH/$CLASS_NAME.class"
exit
*/
class Main
public static void main(String[] args)
return;
D programmers simply put a shebang at the beginning of text file without breaking the syntax:
#!/usr/bin/rdmd
void main()
Sorry for the rollback.
– Pedro Lacerda
Apr 20 '15 at 16:28
1
to pass arguments to executable c++ code, add "$@" after ./a.out;So it would be -------------------------------- //usr/bin/clang++ -O3 -std=c++11 "$0" && ./a.out "$@"; exit
– scinart
Nov 1 '17 at 7:12
thank you @scinart
– Pedro Lacerda
Nov 1 '17 at 13:15
1
Great answer. I would just also check that the existing binary is not outdated.
– Raúl Salinas-Monteagudo
Nov 22 '18 at 13:06
@RaúlSalinas-Monteagudo in the example 4 it can happen indeed, anstat -c %y a.out main.c
comparison would ameliorate. Somewhat between 1 and 2 looks production ready, lol.
– Pedro Lacerda
Feb 21 at 14:32
add a comment |
Short answer:
//usr/bin/clang "$0" && exec ./a.out "$@"
int main()
return 0;
The trick is that your text file must be both valid C/C++ code and shell script. Remember to exit
from the shell script before the interpreter reaches the C/C++ code, or invoke exec
magic.
Run with chmod +x main.c; ./main.c
.
A shebang like #!/usr/bin/tcc -run
isn't needed because unix-like systems will already execute the text file within the shell.
(adapted from this comment)
I used it in my C++ script:
//usr/bin/clang++ -O3 -std=c++11 "$0" && ./a.out; exit
#include <iostream>
int main()
for (auto i: 1, 2, 3)
std::cout << i << std::endl;
return 0;
If your compilation line grows too much you can use the preprocessor (adapted from this answer) as this plain old C code shows:
#if 0
clang "$0" && ./a.out
rm -f ./a.out
exit
#endif
int main()
return 0;
Of course you can cache the executable:
#if 0
EXEC=$0%.*
test -x "$EXEC" || clang "$0" -o "$EXEC"
exec "$EXEC"
#endif
int main()
return 0;
Now, for the truly eccentric Java developer:
/*/../bin/true
CLASS_NAME=$(basename "$0%.*")
CLASS_PATH="$(dirname "$0")"
javac "$0" && java -cp "$CLASS_PATH" $CLASS_NAME
rm -f "$CLASS_PATH/$CLASS_NAME.class"
exit
*/
class Main
public static void main(String[] args)
return;
D programmers simply put a shebang at the beginning of text file without breaking the syntax:
#!/usr/bin/rdmd
void main()
Sorry for the rollback.
– Pedro Lacerda
Apr 20 '15 at 16:28
1
to pass arguments to executable c++ code, add "$@" after ./a.out;So it would be -------------------------------- //usr/bin/clang++ -O3 -std=c++11 "$0" && ./a.out "$@"; exit
– scinart
Nov 1 '17 at 7:12
thank you @scinart
– Pedro Lacerda
Nov 1 '17 at 13:15
1
Great answer. I would just also check that the existing binary is not outdated.
– Raúl Salinas-Monteagudo
Nov 22 '18 at 13:06
@RaúlSalinas-Monteagudo in the example 4 it can happen indeed, anstat -c %y a.out main.c
comparison would ameliorate. Somewhat between 1 and 2 looks production ready, lol.
– Pedro Lacerda
Feb 21 at 14:32
add a comment |
Short answer:
//usr/bin/clang "$0" && exec ./a.out "$@"
int main()
return 0;
The trick is that your text file must be both valid C/C++ code and shell script. Remember to exit
from the shell script before the interpreter reaches the C/C++ code, or invoke exec
magic.
Run with chmod +x main.c; ./main.c
.
A shebang like #!/usr/bin/tcc -run
isn't needed because unix-like systems will already execute the text file within the shell.
(adapted from this comment)
I used it in my C++ script:
//usr/bin/clang++ -O3 -std=c++11 "$0" && ./a.out; exit
#include <iostream>
int main()
for (auto i: 1, 2, 3)
std::cout << i << std::endl;
return 0;
If your compilation line grows too much you can use the preprocessor (adapted from this answer) as this plain old C code shows:
#if 0
clang "$0" && ./a.out
rm -f ./a.out
exit
#endif
int main()
return 0;
Of course you can cache the executable:
#if 0
EXEC=$0%.*
test -x "$EXEC" || clang "$0" -o "$EXEC"
exec "$EXEC"
#endif
int main()
return 0;
Now, for the truly eccentric Java developer:
/*/../bin/true
CLASS_NAME=$(basename "$0%.*")
CLASS_PATH="$(dirname "$0")"
javac "$0" && java -cp "$CLASS_PATH" $CLASS_NAME
rm -f "$CLASS_PATH/$CLASS_NAME.class"
exit
*/
class Main
public static void main(String[] args)
return;
D programmers simply put a shebang at the beginning of text file without breaking the syntax:
#!/usr/bin/rdmd
void main()
Short answer:
//usr/bin/clang "$0" && exec ./a.out "$@"
int main()
return 0;
The trick is that your text file must be both valid C/C++ code and shell script. Remember to exit
from the shell script before the interpreter reaches the C/C++ code, or invoke exec
magic.
Run with chmod +x main.c; ./main.c
.
A shebang like #!/usr/bin/tcc -run
isn't needed because unix-like systems will already execute the text file within the shell.
(adapted from this comment)
I used it in my C++ script:
//usr/bin/clang++ -O3 -std=c++11 "$0" && ./a.out; exit
#include <iostream>
int main()
for (auto i: 1, 2, 3)
std::cout << i << std::endl;
return 0;
If your compilation line grows too much you can use the preprocessor (adapted from this answer) as this plain old C code shows:
#if 0
clang "$0" && ./a.out
rm -f ./a.out
exit
#endif
int main()
return 0;
Of course you can cache the executable:
#if 0
EXEC=$0%.*
test -x "$EXEC" || clang "$0" -o "$EXEC"
exec "$EXEC"
#endif
int main()
return 0;
Now, for the truly eccentric Java developer:
/*/../bin/true
CLASS_NAME=$(basename "$0%.*")
CLASS_PATH="$(dirname "$0")"
javac "$0" && java -cp "$CLASS_PATH" $CLASS_NAME
rm -f "$CLASS_PATH/$CLASS_NAME.class"
exit
*/
class Main
public static void main(String[] args)
return;
D programmers simply put a shebang at the beginning of text file without breaking the syntax:
#!/usr/bin/rdmd
void main()
edited Nov 1 '17 at 13:14
answered Apr 17 '15 at 21:19
Pedro LacerdaPedro Lacerda
627621
627621
Sorry for the rollback.
– Pedro Lacerda
Apr 20 '15 at 16:28
1
to pass arguments to executable c++ code, add "$@" after ./a.out;So it would be -------------------------------- //usr/bin/clang++ -O3 -std=c++11 "$0" && ./a.out "$@"; exit
– scinart
Nov 1 '17 at 7:12
thank you @scinart
– Pedro Lacerda
Nov 1 '17 at 13:15
1
Great answer. I would just also check that the existing binary is not outdated.
– Raúl Salinas-Monteagudo
Nov 22 '18 at 13:06
@RaúlSalinas-Monteagudo in the example 4 it can happen indeed, anstat -c %y a.out main.c
comparison would ameliorate. Somewhat between 1 and 2 looks production ready, lol.
– Pedro Lacerda
Feb 21 at 14:32
add a comment |
Sorry for the rollback.
– Pedro Lacerda
Apr 20 '15 at 16:28
1
to pass arguments to executable c++ code, add "$@" after ./a.out;So it would be -------------------------------- //usr/bin/clang++ -O3 -std=c++11 "$0" && ./a.out "$@"; exit
– scinart
Nov 1 '17 at 7:12
thank you @scinart
– Pedro Lacerda
Nov 1 '17 at 13:15
1
Great answer. I would just also check that the existing binary is not outdated.
– Raúl Salinas-Monteagudo
Nov 22 '18 at 13:06
@RaúlSalinas-Monteagudo in the example 4 it can happen indeed, anstat -c %y a.out main.c
comparison would ameliorate. Somewhat between 1 and 2 looks production ready, lol.
– Pedro Lacerda
Feb 21 at 14:32
Sorry for the rollback.
– Pedro Lacerda
Apr 20 '15 at 16:28
Sorry for the rollback.
– Pedro Lacerda
Apr 20 '15 at 16:28
1
1
to pass arguments to executable c++ code, add "$@" after ./a.out;So it would be -------------------------------- //usr/bin/clang++ -O3 -std=c++11 "$0" && ./a.out "$@"; exit
– scinart
Nov 1 '17 at 7:12
to pass arguments to executable c++ code, add "$@" after ./a.out;So it would be -------------------------------- //usr/bin/clang++ -O3 -std=c++11 "$0" && ./a.out "$@"; exit
– scinart
Nov 1 '17 at 7:12
thank you @scinart
– Pedro Lacerda
Nov 1 '17 at 13:15
thank you @scinart
– Pedro Lacerda
Nov 1 '17 at 13:15
1
1
Great answer. I would just also check that the existing binary is not outdated.
– Raúl Salinas-Monteagudo
Nov 22 '18 at 13:06
Great answer. I would just also check that the existing binary is not outdated.
– Raúl Salinas-Monteagudo
Nov 22 '18 at 13:06
@RaúlSalinas-Monteagudo in the example 4 it can happen indeed, an
stat -c %y a.out main.c
comparison would ameliorate. Somewhat between 1 and 2 looks production ready, lol.– Pedro Lacerda
Feb 21 at 14:32
@RaúlSalinas-Monteagudo in the example 4 it can happen indeed, an
stat -c %y a.out main.c
comparison would ameliorate. Somewhat between 1 and 2 looks production ready, lol.– Pedro Lacerda
Feb 21 at 14:32
add a comment |
$ 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.
I get lots of ld errors with this one :
– Brendan Long
Mar 20 '10 at 8:20
@John Kugelman: What is th need for putting#!/bin/bash /usr/local/bin/runc
as the first line inmain.c
when you are going to strip it usingsed
anyways?
– Lazer
Mar 21 '10 at 2:51
@eSKay - That line tells the system what program to use to "run" the script. Without it bash will try to interpret the.c
file as a bash script and bomb out with a syntax error.
– John Kugelman
Mar 21 '10 at 18:59
@John Kugelman: thanks! I get the complete idea now. very clever!
– Lazer
Mar 21 '10 at 19:09
1
You should use mktemp instead of a.out otherwise you get problems when running two different C-scripts at the same time... Also, the C-script doesn't compile as a real C program because of the hashbang at the top, though I'm not sure what you can do about that...
– Graham
Sep 26 '10 at 12:49
|
show 4 more comments
$ 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.
I get lots of ld errors with this one :
– Brendan Long
Mar 20 '10 at 8:20
@John Kugelman: What is th need for putting#!/bin/bash /usr/local/bin/runc
as the first line inmain.c
when you are going to strip it usingsed
anyways?
– Lazer
Mar 21 '10 at 2:51
@eSKay - That line tells the system what program to use to "run" the script. Without it bash will try to interpret the.c
file as a bash script and bomb out with a syntax error.
– John Kugelman
Mar 21 '10 at 18:59
@John Kugelman: thanks! I get the complete idea now. very clever!
– Lazer
Mar 21 '10 at 19:09
1
You should use mktemp instead of a.out otherwise you get problems when running two different C-scripts at the same time... Also, the C-script doesn't compile as a real C program because of the hashbang at the top, though I'm not sure what you can do about that...
– Graham
Sep 26 '10 at 12:49
|
show 4 more comments
$ 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.
$ 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.
edited Mar 20 '10 at 20:27
answered Mar 20 '10 at 8:08
John KugelmanJohn Kugelman
252k55411463
252k55411463
I get lots of ld errors with this one :
– Brendan Long
Mar 20 '10 at 8:20
@John Kugelman: What is th need for putting#!/bin/bash /usr/local/bin/runc
as the first line inmain.c
when you are going to strip it usingsed
anyways?
– Lazer
Mar 21 '10 at 2:51
@eSKay - That line tells the system what program to use to "run" the script. Without it bash will try to interpret the.c
file as a bash script and bomb out with a syntax error.
– John Kugelman
Mar 21 '10 at 18:59
@John Kugelman: thanks! I get the complete idea now. very clever!
– Lazer
Mar 21 '10 at 19:09
1
You should use mktemp instead of a.out otherwise you get problems when running two different C-scripts at the same time... Also, the C-script doesn't compile as a real C program because of the hashbang at the top, though I'm not sure what you can do about that...
– Graham
Sep 26 '10 at 12:49
|
show 4 more comments
I get lots of ld errors with this one :
– Brendan Long
Mar 20 '10 at 8:20
@John Kugelman: What is th need for putting#!/bin/bash /usr/local/bin/runc
as the first line inmain.c
when you are going to strip it usingsed
anyways?
– Lazer
Mar 21 '10 at 2:51
@eSKay - That line tells the system what program to use to "run" the script. Without it bash will try to interpret the.c
file as a bash script and bomb out with a syntax error.
– John Kugelman
Mar 21 '10 at 18:59
@John Kugelman: thanks! I get the complete idea now. very clever!
– Lazer
Mar 21 '10 at 19:09
1
You should use mktemp instead of a.out otherwise you get problems when running two different C-scripts at the same time... Also, the C-script doesn't compile as a real C program because of the hashbang at the top, though I'm not sure what you can do about that...
– Graham
Sep 26 '10 at 12:49
I get lots of ld errors with this one :
– Brendan Long
Mar 20 '10 at 8:20
I get lots of ld errors with this one :
– Brendan Long
Mar 20 '10 at 8:20
@John Kugelman: What is th need for putting
#!/bin/bash /usr/local/bin/runc
as the first line in main.c
when you are going to strip it using sed
anyways?– Lazer
Mar 21 '10 at 2:51
@John Kugelman: What is th need for putting
#!/bin/bash /usr/local/bin/runc
as the first line in main.c
when you are going to strip it using sed
anyways?– Lazer
Mar 21 '10 at 2:51
@eSKay - That line tells the system what program to use to "run" the script. Without it bash will try to interpret the
.c
file as a bash script and bomb out with a syntax error.– John Kugelman
Mar 21 '10 at 18:59
@eSKay - That line tells the system what program to use to "run" the script. Without it bash will try to interpret the
.c
file as a bash script and bomb out with a syntax error.– John Kugelman
Mar 21 '10 at 18:59
@John Kugelman: thanks! I get the complete idea now. very clever!
– Lazer
Mar 21 '10 at 19:09
@John Kugelman: thanks! I get the complete idea now. very clever!
– Lazer
Mar 21 '10 at 19:09
1
1
You should use mktemp instead of a.out otherwise you get problems when running two different C-scripts at the same time... Also, the C-script doesn't compile as a real C program because of the hashbang at the top, though I'm not sure what you can do about that...
– Graham
Sep 26 '10 at 12:49
You should use mktemp instead of a.out otherwise you get problems when running two different C-scripts at the same time... Also, the C-script doesn't compile as a real C program because of the hashbang at the top, though I'm not sure what you can do about that...
– Graham
Sep 26 '10 at 12:49
|
show 4 more comments
Since the shebang line will be passed to the compiler, and # indicates a preprocessor directive, it will choke on a #!.
What you can do is embed the makefile in the .c file (as discussed in this xkcd thread)
#if 0
make $@ -f - <<EOF
all: foo
foo.o:
cc -c -o foo.o -DFOO_C $0
bar.o:
cc -c -o bar.o -DBAR_C $0
foo: foo.o bar.o
cc -o foo foo.o bar.o
EOF
exit;
#endif
#ifdef FOO_C
#include <stdlib.h>
extern void bar();
int main(int argc, char* argv[])
bar();
return EXIT_SUCCESS;
#endif
#ifdef BAR_C
void bar()
puts("bar!");
#endif
The #if 0 #endif
pair surrounding the makefile ensure the preprocessor ignores that section of text, and the EOF marker marks where the make command should stop parsing input.
1
Not what I was looking for, but close, and definitely entertaining.
– Brendan Long
Mar 20 '10 at 23:08
add a comment |
Since the shebang line will be passed to the compiler, and # indicates a preprocessor directive, it will choke on a #!.
What you can do is embed the makefile in the .c file (as discussed in this xkcd thread)
#if 0
make $@ -f - <<EOF
all: foo
foo.o:
cc -c -o foo.o -DFOO_C $0
bar.o:
cc -c -o bar.o -DBAR_C $0
foo: foo.o bar.o
cc -o foo foo.o bar.o
EOF
exit;
#endif
#ifdef FOO_C
#include <stdlib.h>
extern void bar();
int main(int argc, char* argv[])
bar();
return EXIT_SUCCESS;
#endif
#ifdef BAR_C
void bar()
puts("bar!");
#endif
The #if 0 #endif
pair surrounding the makefile ensure the preprocessor ignores that section of text, and the EOF marker marks where the make command should stop parsing input.
1
Not what I was looking for, but close, and definitely entertaining.
– Brendan Long
Mar 20 '10 at 23:08
add a comment |
Since the shebang line will be passed to the compiler, and # indicates a preprocessor directive, it will choke on a #!.
What you can do is embed the makefile in the .c file (as discussed in this xkcd thread)
#if 0
make $@ -f - <<EOF
all: foo
foo.o:
cc -c -o foo.o -DFOO_C $0
bar.o:
cc -c -o bar.o -DBAR_C $0
foo: foo.o bar.o
cc -o foo foo.o bar.o
EOF
exit;
#endif
#ifdef FOO_C
#include <stdlib.h>
extern void bar();
int main(int argc, char* argv[])
bar();
return EXIT_SUCCESS;
#endif
#ifdef BAR_C
void bar()
puts("bar!");
#endif
The #if 0 #endif
pair surrounding the makefile ensure the preprocessor ignores that section of text, and the EOF marker marks where the make command should stop parsing input.
Since the shebang line will be passed to the compiler, and # indicates a preprocessor directive, it will choke on a #!.
What you can do is embed the makefile in the .c file (as discussed in this xkcd thread)
#if 0
make $@ -f - <<EOF
all: foo
foo.o:
cc -c -o foo.o -DFOO_C $0
bar.o:
cc -c -o bar.o -DBAR_C $0
foo: foo.o bar.o
cc -o foo foo.o bar.o
EOF
exit;
#endif
#ifdef FOO_C
#include <stdlib.h>
extern void bar();
int main(int argc, char* argv[])
bar();
return EXIT_SUCCESS;
#endif
#ifdef BAR_C
void bar()
puts("bar!");
#endif
The #if 0 #endif
pair surrounding the makefile ensure the preprocessor ignores that section of text, and the EOF marker marks where the make command should stop parsing input.
answered Mar 20 '10 at 8:37
EphphathaEphphatha
55827
55827
1
Not what I was looking for, but close, and definitely entertaining.
– Brendan Long
Mar 20 '10 at 23:08
add a comment |
1
Not what I was looking for, but close, and definitely entertaining.
– Brendan Long
Mar 20 '10 at 23:08
1
1
Not what I was looking for, but close, and definitely entertaining.
– Brendan Long
Mar 20 '10 at 23:08
Not what I was looking for, but close, and definitely entertaining.
– Brendan Long
Mar 20 '10 at 23:08
add a comment |
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.
Interesting. I'm hoping for something that would have the same result as gcc $stuff; ./filename though. This is already more than I was expecting though.
– Brendan Long
Mar 20 '10 at 7:52
Brendan - If you want to do that you are going to have to write a script in bash or such to compile and call the program.
– zellio
Mar 20 '10 at 7:53
@Brendan: why do you need this, really? To me it doesn't make much sense using C and C++ this way
– Eli Bendersky
Mar 20 '10 at 7:56
No real need, I was just wondering. It would be a funny way to distribute a program.
– Brendan Long
Mar 20 '10 at 8:00
add a comment |
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.
Interesting. I'm hoping for something that would have the same result as gcc $stuff; ./filename though. This is already more than I was expecting though.
– Brendan Long
Mar 20 '10 at 7:52
Brendan - If you want to do that you are going to have to write a script in bash or such to compile and call the program.
– zellio
Mar 20 '10 at 7:53
@Brendan: why do you need this, really? To me it doesn't make much sense using C and C++ this way
– Eli Bendersky
Mar 20 '10 at 7:56
No real need, I was just wondering. It would be a funny way to distribute a program.
– Brendan Long
Mar 20 '10 at 8:00
add a comment |
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.
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.
answered Mar 20 '10 at 7:50
Eli BenderskyEli Bendersky
172k71302376
172k71302376
Interesting. I'm hoping for something that would have the same result as gcc $stuff; ./filename though. This is already more than I was expecting though.
– Brendan Long
Mar 20 '10 at 7:52
Brendan - If you want to do that you are going to have to write a script in bash or such to compile and call the program.
– zellio
Mar 20 '10 at 7:53
@Brendan: why do you need this, really? To me it doesn't make much sense using C and C++ this way
– Eli Bendersky
Mar 20 '10 at 7:56
No real need, I was just wondering. It would be a funny way to distribute a program.
– Brendan Long
Mar 20 '10 at 8:00
add a comment |
Interesting. I'm hoping for something that would have the same result as gcc $stuff; ./filename though. This is already more than I was expecting though.
– Brendan Long
Mar 20 '10 at 7:52
Brendan - If you want to do that you are going to have to write a script in bash or such to compile and call the program.
– zellio
Mar 20 '10 at 7:53
@Brendan: why do you need this, really? To me it doesn't make much sense using C and C++ this way
– Eli Bendersky
Mar 20 '10 at 7:56
No real need, I was just wondering. It would be a funny way to distribute a program.
– Brendan Long
Mar 20 '10 at 8:00
Interesting. I'm hoping for something that would have the same result as gcc $stuff; ./filename though. This is already more than I was expecting though.
– Brendan Long
Mar 20 '10 at 7:52
Interesting. I'm hoping for something that would have the same result as gcc $stuff; ./filename though. This is already more than I was expecting though.
– Brendan Long
Mar 20 '10 at 7:52
Brendan - If you want to do that you are going to have to write a script in bash or such to compile and call the program.
– zellio
Mar 20 '10 at 7:53
Brendan - If you want to do that you are going to have to write a script in bash or such to compile and call the program.
– zellio
Mar 20 '10 at 7:53
@Brendan: why do you need this, really? To me it doesn't make much sense using C and C++ this way
– Eli Bendersky
Mar 20 '10 at 7:56
@Brendan: why do you need this, really? To me it doesn't make much sense using C and C++ this way
– Eli Bendersky
Mar 20 '10 at 7:56
No real need, I was just wondering. It would be a funny way to distribute a program.
– Brendan Long
Mar 20 '10 at 8:00
No real need, I was just wondering. It would be a funny way to distribute a program.
– Brendan Long
Mar 20 '10 at 8:00
add a comment |
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.
Note that an anonymous suggested edit claims: "It now supports caching. After running a script once, the second time will be practically instant."
– Brock Adams
Jan 1 '16 at 5:04
add a comment |
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.
Note that an anonymous suggested edit claims: "It now supports caching. After running a script once, the second time will be practically instant."
– Brock Adams
Jan 1 '16 at 5:04
add a comment |
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.
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.
edited Jan 1 '16 at 5:03
Brock Adams
70.9k16161220
70.9k16161220
answered Mar 9 '15 at 1:01
ryanmjacobsryanmjacobs
25538
25538
Note that an anonymous suggested edit claims: "It now supports caching. After running a script once, the second time will be practically instant."
– Brock Adams
Jan 1 '16 at 5:04
add a comment |
Note that an anonymous suggested edit claims: "It now supports caching. After running a script once, the second time will be practically instant."
– Brock Adams
Jan 1 '16 at 5:04
Note that an anonymous suggested edit claims: "It now supports caching. After running a script once, the second time will be practically instant."
– Brock Adams
Jan 1 '16 at 5:04
Note that an anonymous suggested edit claims: "It now supports caching. After running a script once, the second time will be practically instant."
– Brock Adams
Jan 1 '16 at 5:04
add a comment |
#!/usr/bin/env sh
tail -n +$(( $LINENO + 1 )) "$0" | cc -xc - && ./a.out "$@"; e="$?"; rm ./a.out; exit "$e";
#include <stdio.h>
int main(int argc, char const* argv[])
printf("Hello world!n");
return 0;
This properly forwards the arguments and the exit code too.
add a comment |
#!/usr/bin/env sh
tail -n +$(( $LINENO + 1 )) "$0" | cc -xc - && ./a.out "$@"; e="$?"; rm ./a.out; exit "$e";
#include <stdio.h>
int main(int argc, char const* argv[])
printf("Hello world!n");
return 0;
This properly forwards the arguments and the exit code too.
add a comment |
#!/usr/bin/env sh
tail -n +$(( $LINENO + 1 )) "$0" | cc -xc - && ./a.out "$@"; e="$?"; rm ./a.out; exit "$e";
#include <stdio.h>
int main(int argc, char const* argv[])
printf("Hello world!n");
return 0;
This properly forwards the arguments and the exit code too.
#!/usr/bin/env sh
tail -n +$(( $LINENO + 1 )) "$0" | cc -xc - && ./a.out "$@"; e="$?"; rm ./a.out; exit "$e";
#include <stdio.h>
int main(int argc, char const* argv[])
printf("Hello world!n");
return 0;
This properly forwards the arguments and the exit code too.
edited Jan 27 '17 at 22:16
answered Jan 26 '17 at 12:29


Tamás ZaholaTamás Zahola
7,40742038
7,40742038
add a comment |
add a comment |
Variatn of John Kugelman can be written in this way:
#!/bin/bash
t=`mktemp`
sed '1,/^//code/d' "$0" | g++ -o "$t" -x c++ - && "$t" "$@"
r=$?
rm -f "$t"
exit $r
//code
#include <stdio.h>
int main()
printf("Hin");
return 0;
This is more than a variation. its a single file implementation and looks nice. The main problem I have with it is that if you load it in a C++ IDE, it will go berserk. you can't hide the shebang, but if you add: /*
after the shebang and#*/
after theexit
command, then the IDE will ignore all the other bash stuff.
– Guss
Dec 19 '16 at 12:55
@Guss, having shebang look like#!/bin/bash : /*
results in error looking for a file: /*
because command line now will look as/bin/bash : /* ./man.c
. Moreover I believe some IDE will report failure for inproper pre-processor instruction#!/bin/bash ...
.
– ony
Dec 20 '16 at 17:53
sorry for not being clear enough in my comment. I meant adding: /*
as the following line after the shebang line. Regarding IDEs not liking the shebang (or the next line that start with:
- yes, probably. The IDEs I normally use mark these as errors but don't make a fuss other than that and the rest of the file is parsed correctly.
– Guss
Dec 21 '16 at 13:54
@Guss, true. That will mark most of the bash code as a comment. Use of#if 0
and#endif
as suggested by @Ephphatha will work also.
– ony
Dec 22 '16 at 15:49
True, but then there's no point in hiding the shell code from the compiler as you do with thesed
expression - you can just give gcc the entire file (minus the shebang). The header then might look like this (note the "n"s in the text, comments are not line oriented):#!/bin/bashn#if 0n t=$(mktemp -u);g++ -o $t -x c++ <(tail -n+2 $0) && $t "$@"; r=$?; rm -f $t; exit $rn#endif
– Guss
Dec 24 '16 at 13:44
|
show 1 more comment
Variatn of John Kugelman can be written in this way:
#!/bin/bash
t=`mktemp`
sed '1,/^//code/d' "$0" | g++ -o "$t" -x c++ - && "$t" "$@"
r=$?
rm -f "$t"
exit $r
//code
#include <stdio.h>
int main()
printf("Hin");
return 0;
This is more than a variation. its a single file implementation and looks nice. The main problem I have with it is that if you load it in a C++ IDE, it will go berserk. you can't hide the shebang, but if you add: /*
after the shebang and#*/
after theexit
command, then the IDE will ignore all the other bash stuff.
– Guss
Dec 19 '16 at 12:55
@Guss, having shebang look like#!/bin/bash : /*
results in error looking for a file: /*
because command line now will look as/bin/bash : /* ./man.c
. Moreover I believe some IDE will report failure for inproper pre-processor instruction#!/bin/bash ...
.
– ony
Dec 20 '16 at 17:53
sorry for not being clear enough in my comment. I meant adding: /*
as the following line after the shebang line. Regarding IDEs not liking the shebang (or the next line that start with:
- yes, probably. The IDEs I normally use mark these as errors but don't make a fuss other than that and the rest of the file is parsed correctly.
– Guss
Dec 21 '16 at 13:54
@Guss, true. That will mark most of the bash code as a comment. Use of#if 0
and#endif
as suggested by @Ephphatha will work also.
– ony
Dec 22 '16 at 15:49
True, but then there's no point in hiding the shell code from the compiler as you do with thesed
expression - you can just give gcc the entire file (minus the shebang). The header then might look like this (note the "n"s in the text, comments are not line oriented):#!/bin/bashn#if 0n t=$(mktemp -u);g++ -o $t -x c++ <(tail -n+2 $0) && $t "$@"; r=$?; rm -f $t; exit $rn#endif
– Guss
Dec 24 '16 at 13:44
|
show 1 more comment
Variatn of John Kugelman can be written in this way:
#!/bin/bash
t=`mktemp`
sed '1,/^//code/d' "$0" | g++ -o "$t" -x c++ - && "$t" "$@"
r=$?
rm -f "$t"
exit $r
//code
#include <stdio.h>
int main()
printf("Hin");
return 0;
Variatn of John Kugelman can be written in this way:
#!/bin/bash
t=`mktemp`
sed '1,/^//code/d' "$0" | g++ -o "$t" -x c++ - && "$t" "$@"
r=$?
rm -f "$t"
exit $r
//code
#include <stdio.h>
int main()
printf("Hin");
return 0;
answered Mar 20 '10 at 9:43
onyony
6,55312536
6,55312536
This is more than a variation. its a single file implementation and looks nice. The main problem I have with it is that if you load it in a C++ IDE, it will go berserk. you can't hide the shebang, but if you add: /*
after the shebang and#*/
after theexit
command, then the IDE will ignore all the other bash stuff.
– Guss
Dec 19 '16 at 12:55
@Guss, having shebang look like#!/bin/bash : /*
results in error looking for a file: /*
because command line now will look as/bin/bash : /* ./man.c
. Moreover I believe some IDE will report failure for inproper pre-processor instruction#!/bin/bash ...
.
– ony
Dec 20 '16 at 17:53
sorry for not being clear enough in my comment. I meant adding: /*
as the following line after the shebang line. Regarding IDEs not liking the shebang (or the next line that start with:
- yes, probably. The IDEs I normally use mark these as errors but don't make a fuss other than that and the rest of the file is parsed correctly.
– Guss
Dec 21 '16 at 13:54
@Guss, true. That will mark most of the bash code as a comment. Use of#if 0
and#endif
as suggested by @Ephphatha will work also.
– ony
Dec 22 '16 at 15:49
True, but then there's no point in hiding the shell code from the compiler as you do with thesed
expression - you can just give gcc the entire file (minus the shebang). The header then might look like this (note the "n"s in the text, comments are not line oriented):#!/bin/bashn#if 0n t=$(mktemp -u);g++ -o $t -x c++ <(tail -n+2 $0) && $t "$@"; r=$?; rm -f $t; exit $rn#endif
– Guss
Dec 24 '16 at 13:44
|
show 1 more comment
This is more than a variation. its a single file implementation and looks nice. The main problem I have with it is that if you load it in a C++ IDE, it will go berserk. you can't hide the shebang, but if you add: /*
after the shebang and#*/
after theexit
command, then the IDE will ignore all the other bash stuff.
– Guss
Dec 19 '16 at 12:55
@Guss, having shebang look like#!/bin/bash : /*
results in error looking for a file: /*
because command line now will look as/bin/bash : /* ./man.c
. Moreover I believe some IDE will report failure for inproper pre-processor instruction#!/bin/bash ...
.
– ony
Dec 20 '16 at 17:53
sorry for not being clear enough in my comment. I meant adding: /*
as the following line after the shebang line. Regarding IDEs not liking the shebang (or the next line that start with:
- yes, probably. The IDEs I normally use mark these as errors but don't make a fuss other than that and the rest of the file is parsed correctly.
– Guss
Dec 21 '16 at 13:54
@Guss, true. That will mark most of the bash code as a comment. Use of#if 0
and#endif
as suggested by @Ephphatha will work also.
– ony
Dec 22 '16 at 15:49
True, but then there's no point in hiding the shell code from the compiler as you do with thesed
expression - you can just give gcc the entire file (minus the shebang). The header then might look like this (note the "n"s in the text, comments are not line oriented):#!/bin/bashn#if 0n t=$(mktemp -u);g++ -o $t -x c++ <(tail -n+2 $0) && $t "$@"; r=$?; rm -f $t; exit $rn#endif
– Guss
Dec 24 '16 at 13:44
This is more than a variation. its a single file implementation and looks nice. The main problem I have with it is that if you load it in a C++ IDE, it will go berserk. you can't hide the shebang, but if you add
: /*
after the shebang and #*/
after the exit
command, then the IDE will ignore all the other bash stuff.– Guss
Dec 19 '16 at 12:55
This is more than a variation. its a single file implementation and looks nice. The main problem I have with it is that if you load it in a C++ IDE, it will go berserk. you can't hide the shebang, but if you add
: /*
after the shebang and #*/
after the exit
command, then the IDE will ignore all the other bash stuff.– Guss
Dec 19 '16 at 12:55
@Guss, having shebang look like
#!/bin/bash : /*
results in error looking for a file : /*
because command line now will look as /bin/bash : /* ./man.c
. Moreover I believe some IDE will report failure for inproper pre-processor instruction #!/bin/bash ...
.– ony
Dec 20 '16 at 17:53
@Guss, having shebang look like
#!/bin/bash : /*
results in error looking for a file : /*
because command line now will look as /bin/bash : /* ./man.c
. Moreover I believe some IDE will report failure for inproper pre-processor instruction #!/bin/bash ...
.– ony
Dec 20 '16 at 17:53
sorry for not being clear enough in my comment. I meant adding
: /*
as the following line after the shebang line. Regarding IDEs not liking the shebang (or the next line that start with :
- yes, probably. The IDEs I normally use mark these as errors but don't make a fuss other than that and the rest of the file is parsed correctly.– Guss
Dec 21 '16 at 13:54
sorry for not being clear enough in my comment. I meant adding
: /*
as the following line after the shebang line. Regarding IDEs not liking the shebang (or the next line that start with :
- yes, probably. The IDEs I normally use mark these as errors but don't make a fuss other than that and the rest of the file is parsed correctly.– Guss
Dec 21 '16 at 13:54
@Guss, true. That will mark most of the bash code as a comment. Use of
#if 0
and #endif
as suggested by @Ephphatha will work also.– ony
Dec 22 '16 at 15:49
@Guss, true. That will mark most of the bash code as a comment. Use of
#if 0
and #endif
as suggested by @Ephphatha will work also.– ony
Dec 22 '16 at 15:49
True, but then there's no point in hiding the shell code from the compiler as you do with the
sed
expression - you can just give gcc the entire file (minus the shebang). The header then might look like this (note the "n"s in the text, comments are not line oriented): #!/bin/bashn#if 0n t=$(mktemp -u);g++ -o $t -x c++ <(tail -n+2 $0) && $t "$@"; r=$?; rm -f $t; exit $rn#endif
– Guss
Dec 24 '16 at 13:44
True, but then there's no point in hiding the shell code from the compiler as you do with the
sed
expression - you can just give gcc the entire file (minus the shebang). The header then might look like this (note the "n"s in the text, comments are not line oriented): #!/bin/bashn#if 0n t=$(mktemp -u);g++ -o $t -x c++ <(tail -n+2 $0) && $t "$@"; r=$?; rm -f $t; exit $rn#endif
– Guss
Dec 24 '16 at 13:44
|
show 1 more comment
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 ] &&
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?
add a comment |
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 ] &&
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?
add a comment |
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 ] &&
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?
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 ] &&
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?
edited Nov 22 '18 at 13:17
answered Nov 22 '18 at 11:46
Raúl Salinas-MonteagudoRaúl Salinas-Monteagudo
2,25911218
2,25911218
add a comment |
add a comment |
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 worldn");
return 0;
add a comment |
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 worldn");
return 0;
add a comment |
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 worldn");
return 0;
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 worldn");
return 0;
edited Sep 25 '17 at 14:09
answered Apr 10 '17 at 14:32


d99krisd99kris
1557
1557
add a comment |
add a comment |
Thanks for contributing an answer to Stack Overflow!
- Please be sure to answer the question. Provide details and share your research!
But avoid …
- Asking for help, clarification, or responding to other answers.
- Making statements based on opinion; back them up with references or personal experience.
To learn more, see our tips on writing great answers.
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
StackExchange.ready(
function ()
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f2482348%2frun-c-or-c-file-as-a-script%23new-answer', 'question_page');
);
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
l,DZ qFKR5M1RX9DvydZhaSZr,Fl78LOz,64Z,Yq ydEfuAf3fUGLoboc sKomZKR1,zh6C qvEFLj7eY Fcul357du
3
There are interpreters: cint, ch; plus igcc and tcc will act like one. There are some questions about them around here somewhere: stackoverflow.com/questions/69539/… stackoverflow.com/questions/584714/… and probably a few others. And this may be a duplicate: stackoverflow.com/questions/2277865/…
– dmckee
Mar 20 '10 at 8:15