C- oder C++-Datei als Skript ausführen

Lesezeit: 7 Minuten

Das ist also wahrscheinlich ein langer Weg, aber gibt es eine Möglichkeit, eine C- oder C++-Datei als Skript auszuführen? Ich habe es versucht:

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

int main(){ return 0; }

Aber es heißt:

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

  • Es gibt Dolmetscher: cint, ch; plus igcc und tcc verhalten sich wie eins. Es gibt hier irgendwo einige Fragen dazu: stackoverflow.com/questions/69539/… stackoverflow.com/questions/584714/… und wahrscheinlich noch ein paar andere. Und dies könnte ein Duplikat sein: stackoverflow.com/questions/2277865/…

    – dmckee — Ex-Moderator-Kätzchen

    20. März 2010 um 8:15 Uhr


Benutzeravatar von Pedro Lacerda
Pedro Lacerda

Kurze Antwort:

//usr/bin/clang "$0" && exec ./a.out "$@"
int main(){
    return 0;
}

Der Trick besteht darin, dass Ihre Textdatei sowohl gültiger C/C++-Code als auch Shell-Skript sein muss. Erinnere dich an exit aus dem Shell-Skript, bevor der Interpreter den C/C++-Code erreicht, oder aufrufen exec Magie.

Lauf mit chmod +x main.c; ./main.c.

Ein Kram wie #!/usr/bin/tcc -run wird nicht benötigt, da Unix-ähnliche Systeme die Textdatei bereits in der Shell ausführen.

(angepasst von dieser Kommentar)


Ich habe es in meinem C++-Skript verwendet:

//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;
}

Wenn Ihre Kompilierungszeile zu stark wächst, können Sie den Präprozessor (angepasst an diese Antwort) verwenden, wie dieser einfache alte C-Code zeigt:

#if 0
    clang "$0" && ./a.out
    rm -f ./a.out
    exit
#endif
int main() {
    return 0;
}

Natürlich können Sie die ausführbare Datei zwischenspeichern:

#if 0
    EXEC=${0%.*}
    test -x "$EXEC" || clang "$0" -o "$EXEC"
    exec "$EXEC"
#endif
int main() {
    return 0;
}

Nun, für den wirklich exzentrischen Java-Entwickler:

/*/../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-Programmierer setzen einfach einen Shebang an den Anfang der Textdatei, ohne die Syntax zu brechen:

#!/usr/bin/rdmd
void main(){}

Sehen:

  • Sorry für den Rollback.

    – Pedro Lacerda

    20. April 2015 um 16:28 Uhr

  • Um Argumente an ausführbaren C++-Code zu übergeben, fügen Sie “$@” nach ./a.out hinzu; So wäre es ——————— —— //usr/bin/clang++ -O3 -std=c++11 “$0” && ./a.out “$@”; Ausfahrt

    – scinart

    1. November 2017 um 7:12 Uhr


  • Gute Antwort. Ich würde einfach auch überprüfen, ob die vorhandene Binärdatei nicht veraltet ist.

    – Raúl Salinas-Monteagudo

    22. November 2018 um 13:06 Uhr

  • @RaúlSalinas-Monteagudo im Beispiel 4 kann es ja passieren, an stat -c %y a.out main.c ein vergleich würde helfen. Etwas zwischen 1 und 2 sieht produktionsreif aus, lol.

    – Pedro Lacerda

    21. Februar 2019 um 14:32 Uhr

  • Unix erlaubt also beide Formen von Shebang #! und //. Irgendeine Idee, wo das dokumentiert ist?

    – MenschlichkeitUNDFrieden

    19. Juni 2019 um 7:40 Uhr

Für C können Sie einen Blick auf werfen tcc, der Tiny-C-Compiler. Das Ausführen von C-Code als Skript ist eine seiner möglichen Anwendungen.

  • Oh, ich mag diese. Alles, was Sie tun müssen, ist hinzuzufügen #!/usr/bin/tcc -run

    – Brendan Lange

    20. März 2010 um 8:04 Uhr

  • @Brendan: Ich mag tcc auch sehr, besonders in Bezug auf Kompilierzeiten; Sie müssen sich jedoch vor Compiler-Bugs hüten

    – Christoph

    20. März 2010 um 8:34 Uhr

Benutzeravatar von John Kugelman
John Kugelmann

$ 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!

Der Befehl sed übernimmt die .c Datei und streift die Hash-Bang-Linie ab. 2,$p bedeutet Zeilen 2 bis Dateiende drucken; "$@" erweitert die Befehlszeilenargumente zum runc-Skript, dh "main.c".

Die Ausgabe von sed wird an gcc geleitet. Vorbeigehen - to gcc weist es an, von stdin zu lesen, und wenn Sie das tun, müssen Sie auch die Quellsprache mit angeben -x da es keinen Dateinamen hat, aus dem man raten könnte.

  • @John Kugelman: Was braucht man zum Putten? #!/bin/bash /usr/local/bin/runc als erste Zeile ein main.c wenn Sie es mit abstreifen werden sed Sowieso?

    – Laser

    21. März 2010 um 2:51 Uhr

  • @eSKay – Diese Zeile teilt dem System mit, welches Programm zum “Ausführen” des Skripts verwendet werden soll. Ohne es wird bash versuchen, die zu interpretieren .c Datei als Bash-Skript und bombardieren mit einem Syntaxfehler.

    – John Kugelmann

    21. März 2010 um 18:59 Uhr

  • @ John Kugelmann: danke! Ich habe jetzt die vollständige Idee. sehr schlau!

    – Laser

    21. März 2010 um 19:09 Uhr

  • Sie sollten mktemp anstelle von a.out verwenden, da Sie sonst Probleme bekommen, wenn Sie zwei verschiedene C-Skripte gleichzeitig ausführen … Außerdem wird das C-Skript aufgrund des Hashbangs am Anfang nicht als echtes C-Programm kompiliert. obwohl ich mir nicht sicher bin, was du dagegen tun kannst…

    – Graham

    26. September 2010 um 12:49 Uhr


  • @Graham Nun, deshalb entfernt er das #! mit sed vor dem Kompilieren.

    – Spitze

    26. September 2010 um 13:17 Uhr

Da die Shebang-Zeile an den Compiler übergeben wird und # eine Präprozessordirektive angibt, wird sie an einem #! ersticken.

Sie können das Makefile in die .c-Datei einbetten (wie in dieser 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

Das #if 0 #endif Ein Paar, das das Makefile umgibt, stellt sicher, dass der Präprozessor diesen Textabschnitt ignoriert, und die EOF-Markierung markiert, wo der make-Befehl mit dem Analysieren der Eingabe aufhören soll.

CINT:

CINT ist ein Interpreter für C- und C++-Code. Dies ist zB für Situationen nützlich, in denen schnelle Entwicklung wichtiger ist als Ausführungszeit. Durch die Verwendung eines Interpreters wird der Kompilier- und Verknüpfungszyklus drastisch reduziert, was eine schnelle Entwicklung ermöglicht. CINT macht die C/C++-Programmierung auch für Teilzeit-Programmierer zum Vergnügen.

  • Interessant. Ich hoffe auf etwas, das das gleiche Ergebnis wie gcc $stuff haben würde; ./Dateiname aber. Das ist aber schon mehr als ich erwartet hatte.

    – Brendan Lang

    20. März 2010 um 7:52 Uhr

  • Brendan – Wenn Sie das tun möchten, müssen Sie ein Skript in Bash oder ähnlichem schreiben, um das Programm zu kompilieren und aufzurufen.

    – Zellio

    20. März 2010 um 7:53 Uhr

  • @Brendan: Warum brauchst du das wirklich? Für mich macht es nicht viel Sinn, C und C++ auf diese Weise zu verwenden

    – Eli Bendersky

    20. März 2010 um 7:56 Uhr

  • Keine wirkliche Notwendigkeit, ich habe mich nur gefragt. Es wäre eine lustige Art, ein Programm zu verteilen.

    – Brendan Lang

    20. März 2010 um 8:00 Uhr

Benutzeravatar von Brock Adams
Rock Adams

Vielleicht möchten Sie zur Kasse gehen ryanmjacobs/c die dafür konzipiert wurde. Es fungiert als Wrapper um Ihren bevorzugten Compiler.

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

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

Das Schöne an der Nutzung c ist, dass Sie auswählen können, welchen Compiler Sie verwenden möchten, z

$ export CC=clang
$ export CC=gcc

So erhalten Sie auch alle Ihre bevorzugten Optimierungen! Schlag das tcc -run!

Sie können dem Shebang auch Compiler-Flags hinzufügen, solange sie mit dem abgeschlossen werden -- Figuren:

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

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

c verwendet auch $CFLAGS und $CPPFLAGS wenn sie auch eingestellt sind.

  • Interessant. Ich hoffe auf etwas, das das gleiche Ergebnis wie gcc $stuff haben würde; ./Dateiname aber. Das ist aber schon mehr als ich erwartet hatte.

    – Brendan Lang

    20. März 2010 um 7:52 Uhr

  • Brendan – Wenn Sie das tun möchten, müssen Sie ein Skript in Bash oder ähnlichem schreiben, um das Programm zu kompilieren und aufzurufen.

    – Zellio

    20. März 2010 um 7:53 Uhr

  • @Brendan: Warum brauchst du das wirklich? Für mich macht es nicht viel Sinn, C und C++ auf diese Weise zu verwenden

    – Eli Bendersky

    20. März 2010 um 7:56 Uhr

  • Keine wirkliche Notwendigkeit, ich habe mich nur gefragt. Es wäre eine lustige Art, ein Programm zu verteilen.

    – Brendan Lang

    20. März 2010 um 8:00 Uhr

#!/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;
}

Dadurch werden die Argumente und der Exit-Code auch ordnungsgemäß weitergeleitet.

1433580cookie-checkC- oder C++-Datei als Skript ausführen

This website is using cookies to improve the user-friendliness. You agree by using the website further.

Privacy policy