Preprocessor C

mogbo

Banned
Hallo,
habe ein recht unspektakuläres Problem, welches ich mit dem Präprozessor lösen wollte (wüsste auch nicht wie sonst):

Code:
#if defined (_WIN64) || (_WIN32)
#    include <windows.h>
#    include <malloc.h>
#    include <conio.h>
#    define CLEAR system("cls")
#    define BUF 256
#elif defined (BSD)
#    include <err.h>
#    include <unistd.h>
#    define CLEAR printf("\e[1;1H\e[2J")
#endif

void                 err(int, const char *, ...)
Habe mir für den Fall von Windows eine eigene err() gebastelt und würde diese nun gerne einbinden (nur bei Windows).
Falls ich das err() in eine eigene *.h packe würds klappen, ich würde es jedoch gerne direkt in den Code verbauen... Gibt es dafür eine Lösung?
 
Falls ich das err() in eine eigene *.h packe würds klappen, ich würde es jedoch gerne direkt in den Code verbauen... Gibt es dafür eine Lösung?
Ich weiss nicht ob ich dich richtig verstanden haben, aber entweder die Funktionen als inline declarieren oder eben als macro. Und dann das .h File importieren.
 
Hallo,
habe ein recht unspektakuläres Problem, welches ich mit dem Präprozessor lösen wollte (wüsste auch nicht wie sonst):

Code:
# ...
#    define CLEAR printf("\e[1;1H\e[2J")
#

Was macht denn die Escape Seqenz, die Du als Parameter an printf übergibst?

ClearScreen?
 
Was macht denn die Escape Seqenz, die Du als Parameter an printf übergibst?

ClearScreen?
Equivalent zum clear in der Shell --> ClearScreen
Habe es 2mal definiert, da Windows so keinen ClearScreen erzeugen kann.

Ich weiss nicht ob ich dich richtig verstanden haben, aber entweder die Funktionen als inline declarieren oder eben als macro. Und dann das .h File importieren.
Ich wollte das Importieren eines .h vermeiden.

Ich habe bei OpenBSD eine <err.h>, bei Windows habe ich diese nicht, darum habe ich eine eigene err() gebastelt, die jedoch nur im Falle von Windows verwendet werden soll.

void err(int, const char *, ...)
Wie kann ich diese Zeile inline definieren, damit sie mit allen Zeilen im Code kompatibel bleibt, zB:

Code:
if ((ptr = malloc(sizeof(struct node))) == NULL)
    err(EXIT_FAILURE, "%s: malloc() failure", __func__);
Diese Zeile soll immer funktionieren, egal ob ich jetzt ein *BSD oder Windows verwende, bei Windows soll es aber die selbstgebaute Funktion verwenden, ohne *.h include
 
Diese Zeile soll immer funktionieren, egal ob ich jetzt ein *BSD oder Windows verwende

err(3) ist in der libc ja so schon definiert.
Wenn Windows diese Funktion nicht kennt, baust du dir z.B. ein windows_err(), das die gleichen Parameter übernimmt wie err(3).
Den Präprozessor nutzt du dann dafür, err() im Quelltext durch windows_err() zu ersetzen, wenn diese Plattform erkannt wurde.

Code:
#ifdef winbloed
#define err(...) windows_err(__VA_ARGS__)
#endif

So oder so brauchst du eine Funktionsdefinition und die eigentliche Implementierung für windows_err(). Wenn überhaupt kommt nur die Definition in ein Headerfile, die Implementierung hat dort eigentlich nichts zu suchen. Daher ist deine Anforderung "ohne *.h include" irreführend.

Rob
 
In größeren Projekten kann es eine gute Idee sein sich gleich eigene Source-Dateien für die jeweilige Plattform zu gönnen und durch das Build-System entscheiden lassen, welche gelinkt werden muss als. Als Beispiel:

Code:
// platform.h ist ein Header, der allen
// plattformabhängigen Kram definiert.
void sys_err(int eval, const char *fmt, ...);


// windows.c ist die Implementierung für Windows.
void sys_err(int eval, const char *fmt, ...)
{
    // Implementierung von sys_err() für Windows.
}


// unix.c ist die Implementierung für unixoide Systeme.
void sys_err(int eval, const char *fmt, ...)
{
    va_list argptr;
    va_start(argptr, fmt);
    verr(eval, fmt, argptr);
    va_end(argptr);
}

Wenn es um etwa komplexere Dinge geht, kommt man um solche mächtigeren Abstraktionssysteme nicht mehr drum herum. Die paar CPU-Zyklen für den zusätzlichen Funktionsaufruf tun wirklich niemanden mehr weh, wenn man nicht absolut krank-krass auf Performance optimieren muss und es ist wesentlich schöner, lesbarer und nachvollziehbarer, als wenn man unendliche Präprozessororgien baut. Und es ist portabler als ein mächtiges, aber undurchschaubares System wie Automake (aus guten Gründen meist Autobreak genannt), was detalliert prüft, was die jeweilige Plattform kann und was nicht.

Nachtrag: Generell ist es aber eine gute Idee, wenn möglich standardisierte Funktionen zu nutzen. err() ist beispielsweise ein BSDism, glibc kann's noch, danach wird die Luft aber schnell recht dünn. Ein paar Zeilen um strerror() können später viel Ärger ersparen. Leider ist aber ausgerechnet in MSVC die Unterstützung von vielen DIngen, die nach C89 kamen, nach wie vor durchwachsen. Deshalb ist dieser Ratschlag in Richtung Windows mit etwas Vorsicht zu genießen.

Nachtrag 2: Es muss im Beispiel natürlich verr() statt err() sein.
 
Zuletzt bearbeitet:
So oder so brauchst du eine Funktionsdefinition und die eigentliche Implementierung für windows_err(). Wenn überhaupt kommt nur die Definition in ein Headerfile, die Implementierung hat dort eigentlich nichts zu suchen. Daher ist deine Anforderung "ohne *.h include" irreführend.
Ich wollte das eigentlich relativ kleine Tool (450 Zeilen) auf eine *.c Datei beschränken, darum ohne eigene Header :)

Aber danke für den Ansatz, damit kann ich schonmal bissl was bauen.

Ein paar Zeilen um strerror() können später viel Ärger ersparen
Ich schaue mal rein, hab ich bisher nie genutzt

Danke für den Codefetzen, schaue ich mir morgen mal genauer an!
 
Irgendie verstehe ich dein Problem nicht so ganz.
Du hast eine eigene err() gestrickt und die brauchst du nur in der einen .c-Datei.
Was hindert dich daran, die in den Abschnitt #if defined (_WIN64) || (_WIN32) zu packen?

Nebenbei: Es ist hübscher, wenn _WIN32 ebenfalls per defined geprüft wird.
Zudem ist das Prüfen von _WIN64 redundant, da _WIN32 dann auf jeden Fall auch gesetzt ist.
 
Irgendie verstehe ich dein Problem nicht so ganz.
Du hast eine eigene err() gestrickt und die brauchst du nur in der einen .c-Datei.
Was hindert dich daran, die in den Abschnitt #if defined (_WIN64) || (_WIN32) zu packen?
Wenn man nicht den passenden Syntax kennt, erweißt sich das als schwierig

Zudem ist das Prüfen von _WIN64 redundant, da _WIN32 dann auf jeden Fall auch gesetzt ist.
Schlechtes Beispiel gewählt :)
 
Wenn man nicht den passenden Syntax kennt, erweißt sich das als schwierig
Welche passende Syntax?
Du hast doch schon alles.

Code:
#if defined(_WIN32)
#    include <windows.h>
#    include <malloc.h>
#    include <conio.h>
#    define CLEAR system("cls")
#    define BUF 256

void err(int eval, char const* fmt, ...)
{
  // Implementierung der Funktion
}
#elif


Vielen Dank, ich bin auf meinen Lösungsweg gekommen
Der da wäre?
 
#define err(...) windows_err(__VA_ARGS__)
Ist meine Zwischenlösung, bis ich mir eine allgemeine Bibliothek für OpenBSD <=> Windows gebastelt habe.

#if defined(_WIN32) # include <windows.h> # include <malloc.h> # include <conio.h> # define CLEAR system("cls") # define BUF 256 void err(int eval, char const* fmt, ...) { // Implementierung der Funktion } #elif
Ach ich kann die ganze Funktion da rein setzen, war mir nicht wirklich bewusst
 
Der include-Befehl ist ebenso nur eine Anweisung für den Präprozessor: binde die angegebene Datei hier ein.
Ob du die Definition in einer externen Datei oder lokal machst, spielt absolut keine Rolle und ist generell dir allein überlassen.
Schon klar, ich verschicke die Source aber über scp und wollte daher immer nur eine Datei hin- und herschieben (reine Bequemlichkeit) bzw. Copy + Paste
 
Zurück
Oben