C-Standardargumente

Lesezeit: 7 Minuten

Benutzeravatar von Nathaniel Flath
Nathaniel Flat

Gibt es eine Möglichkeit, Standardargumente für eine Funktion in C anzugeben?

  • wollen nur ein etwas besseres C, nicht C++. Denken Sie an C+. mit einer Vielzahl kleiner Verbesserungen aus C++, aber nicht dem großen Durcheinander. Und bitte kein anderer Link-Loader. sollte nur ein weiterer Präprozessor-ähnlicher Schritt sein. standardisiert. überall, überallhin, allerorts…

    – ivo Welch

    15. Februar 2015 um 4:40 Uhr


  • Verwandte Frage, die ich nicht in der Seitenleiste aufgelistet gesehen habe.

    – Shelby Moore III

    18. November 2015 um 14:34 Uhr

  • Ich würde sagen, hör auf, ein Barbar zu sein und lerne, C++ (11, …) zu benutzen, nun ja – jk! /me löscht Flammen … aber … du wirst es lieben … hahaha, ich kann mir nicht helfen, sorry.

    – Stimmungsboom

    17. März 2017 um 17:43 Uhr

  • Mögliches Duplikat von Standardwerten für Argumente in C-Funktionen und Funktionsüberladung in C

    – Jonathan Mei

    6. April 2018 um 13:53 Uhr

Benutzeravatar von bk
schwarz

Wow, jeder hier ist so ein Pessimist. Die Antwort ist ja.

Es ist nicht trivial: Am Ende haben wir die Kernfunktion, eine unterstützende Struktur, eine Wrapper-Funktion und ein Makro um die Wrapper-Funktion herum. In meiner Arbeit habe ich eine Reihe von Makros, um all dies zu automatisieren; Sobald Sie den Fluss verstehen, wird es Ihnen leicht fallen, dasselbe zu tun.

Ich habe dies an anderer Stelle geschrieben, daher hier ein detaillierter externer Link, um die Zusammenfassung hier zu ergänzen: http://modelingwithdata.org/arch/00000022.htm

Wir möchten umkehren

double f(int i, double x)

in eine Funktion, die Standardwerte übernimmt (i=8, x=3,14). Definieren Sie eine Begleitstruktur:

typedef struct {
    int i;
    double x;
} f_args;

Benennen Sie Ihre Funktion um f_baseund definieren Sie eine Wrapper-Funktion, die Standardwerte festlegt und die Basis aufruft:

double var_f(f_args in){
    int i_out = in.i ? in.i : 8;
    double x_out = in.x ? in.x : 3.14;
    return f_base(i_out, x_out);
}

Fügen Sie nun ein Makro hinzu, indem Sie die Variadic-Makros von C verwenden. Auf diese Weise müssen Benutzer nicht wissen, dass sie tatsächlich a ausfüllen f_args struct und denken, dass sie das Übliche tun:

#define f(...) var_f((f_args){__VA_ARGS__});

OK, jetzt würde alles folgende funktionieren:

f(3, 8);      //i=3, x=8
f(.i=1, 2.3); //i=1, x=2.3
f(2);         //i=2, x=3.14
f(.x=9.2);    //i=8, x=9.2

Überprüfen Sie die Regeln dazu, wie zusammengesetzte Initialisierer Standardwerte für die genauen Regeln festlegen.

Eine Sache, die nicht funktionieren wird: f(0), weil wir nicht zwischen einem fehlenden Wert und Null unterscheiden können. Meiner Erfahrung nach ist dies etwas, auf das man achten sollte, aber es kann bei Bedarf erledigt werden – in der Hälfte der Zeit ist Ihr Standardwert wirklich Null.

Ich habe mir die Mühe gemacht, dies zu schreiben, weil ich denke, dass benannte Argumente und Standardwerte das Codieren in C wirklich einfacher machen und sogar noch mehr Spaß machen. Und C ist großartig, weil es so einfach ist und trotzdem genug da ist, um all dies zu ermöglichen.

  • +1 kreativ! Es hat seine Grenzen, bringt aber auch benannte Parameter in die Tabelle. Beachten Sie, dass, {} (leerer Initialisierer) ist ein Fehler C99.

    – u0b34a0f6ae

    29. Oktober 2011 um 3:45 Uhr

  • Hier ist jedoch etwas Großartiges für Sie: Der Standard erlaubt die mehrfache Angabe benannter Elemente, die später überschrieben werden. Nur für benannte Parameter können Sie also das Standardproblem lösen und einen leeren Aufruf zulassen. #define vrange(...) CALL(range,(param){.from=1, .to=100, .step=1, __VA_ARGS__})

    – u0b34a0f6ae

    29. Oktober 2011 um 4:58 Uhr

  • Ich hoffe, die Compilerfehler sind lesbar, aber das ist eine großartige Technik! Sieht fast aus wie Python-Kwargs.

    – zwei

    21. Juni 2012 um 16:59 Uhr

  • @RunHolt Obwohl sicherlich einfacher, ist es nicht objektiv besser; Benannte Parameter haben Vorteile wie die einfache Lesbarkeit von Aufrufen (auf Kosten der Lesbarkeit des Quellcodes). Einer ist besser für Entwickler der Quelle, der andere besser für Benutzer der Funktion. Es ist ein wenig voreilig, einfach “das hier ist besser!”

    – Alice

    25. April 2014 um 19:26 Uhr

  • @DawidPi: C11 6.7.9 (19), beim Initialisieren von Aggregaten: “Alle Unterobjekte, die nicht explizit initialisiert werden, werden implizit genauso initialisiert wie Objekte mit statischer Speicherdauer.” Und wie Sie wissen, werden Elemente mit statischer Dauer auf Null initialisiert |NULL|\0. [This was in c99 too.]

    – schwarz.

    4. April 2016 um 17:06 Uhr

Ja. 🙂 Aber nicht so, wie man es erwarten würde.

int f1(int arg1, double arg2, char* name, char *opt);

int f2(int arg1, double arg2, char* name)
{
  return f1(arg1, arg2, name, "Some option");
}

Leider erlaubt C Ihnen nicht, Methoden zu überladen, so dass Sie am Ende zwei verschiedene Funktionen haben würden. Wenn Sie jedoch f2 aufrufen, rufen Sie tatsächlich f1 mit einem Standardwert auf. Dies ist eine “Don’t Repeat Yourself”-Lösung, die Ihnen hilft, das Kopieren/Einfügen von vorhandenem Code zu vermeiden.

  • FWIW, ich würde es vorziehen, die Zahl am Ende der Funktion zu verwenden, um die Anzahl der benötigten Argumente anzugeben. Macht es einfacher, als nur eine beliebige Zahl zu verwenden. 🙂

    – Macke

    31. Oktober 2011 um 12:51 Uhr

  • Dies ist bei weitem die beste Antwort, da es eine einfache Möglichkeit zeigt, dasselbe Ziel zu erreichen. Ich habe eine Funktion, die Teil einer festen API ist, die ich nicht ändern möchte, aber ich brauche sie, um einen neuen Parameter zu übernehmen. Natürlich ist es so offensichtlich, dass ich es übersehen habe (bin beim Denken an die Standardparameter hängen geblieben!)

    – RunHolt

    11. Oktober 2013 um 20:01 Uhr

  • f2 könnte auch ein Präprozessor-Makro sein

    – osven

    21. März 2017 um 16:06 Uhr

Benutzeravatar von Eli Courtwright
Eli Gerichtsschreiber

Nicht wirklich. Der einzige Weg wäre Schreiben Sie eine varargs-Funktion und füllen Sie manuell Standardwerte für Argumente aus, die der Aufrufer nicht übergibt.

  • Ich hasse den Mangel an Überprüfung bei der Verwendung von Varargs.

    – dmckee — Ex-Moderator-Kätzchen

    24. September 2009 um 15:03 Uhr

  • Das sollten Sie auch; Ich empfehle das eigentlich nicht; Ich wollte nur vermitteln, dass es möglich ist.

    – Eli Courtwright

    24. September 2009 um 15:17 Uhr

  • Wie wollen Sie jedoch überprüfen, ob der Anrufer das Argument weitergibt oder nicht? Ich denke, damit das funktioniert, haben Sie nicht den Anrufer, der Ihnen sagt, dass er es nicht bestanden hat? Ich denke, das macht den ganzen Ansatz etwas weniger brauchbar – der Aufrufer könnte auch eine Funktion mit einem anderen Namen aufrufen.

    – Johannes Schaub – litb

    24. September 2009 um 18:21 Uhr

  • Das open(2) Der Systemaufruf verwendet dies für ein optionales Argument, das abhängig von den erforderlichen Argumenten vorhanden sein kann, und printf(3) liest einen Formatstring, der angibt, wie viele Argumente es geben wird. Beide verwenden Varargs ziemlich sicher und effektiv, und obwohl Sie sie sicherlich vermasseln können, printf() scheint besonders beliebt zu sein.

    – Chris Lutz

    24. September 2009 um 19:55 Uhr

  • @Eli: Nicht alle C-Compiler sind gcc. Es gibt eine fortgeschrittene Compiler-Magie, die Sie warnt, wenn Ihre printf()-Argumente nicht mit Ihrer Formatzeichenfolge übereinstimmen. Und ich glaube nicht, dass es möglich ist, ähnliche Warnungen für Ihre eigenen variadischen Funktionen zu erhalten (es sei denn, sie verwenden denselben Stil der Formatzeichenfolge).

    – Tomlogik

    14. Juni 2010 um 19:18 Uhr

Benutzeravatar von u0b34a0f6ae
u0b34a0f6ae

Wir können Funktionen erstellen, die benannte Parameter (nur) für Standardwerte verwenden. Dies ist eine Fortsetzung der Antwort von bk.

#include <stdio.h>                                                               

struct range { int from; int to; int step; };
#define range(...) range((struct range){.from=1,.to=10,.step=1, __VA_ARGS__})   

/* use parentheses to avoid macro subst */             
void (range)(struct range r) {                                                     
    for (int i = r.from; i <= r.to; i += r.step)                                 
        printf("%d ", i);                                                        
    puts("");                                                                    
}                                                                                

int main() {                                                                     
    range();                                                                    
    range(.from=2, .to=4);                                                      
    range(.step=2);                                                             
}    

Der C99-Standard definiert, dass spätere Namen in der Initialisierung vorherige Elemente überschreiben. Wir können auch einige standardmäßige Positionsparameter haben, ändern Sie einfach das Makro und die Funktionssignatur entsprechend. Die Standardwertparameter können nur im benannten Parameterstil verwendet werden.

Programmausgabe:

1 2 3 4 5 6 7 8 9 10 
2 3 4 
1 3 5 7 9

OpenCV verwendet so etwas wie:

/* in the header file */

#ifdef __cplusplus
    /* in case the compiler is a C++ compiler */
    #define DEFAULT_VALUE(value) = value
#else
    /* otherwise, C compiler, do nothing */
    #define DEFAULT_VALUE(value)
#endif

void window_set_size(unsigned int width  DEFAULT_VALUE(640),
                     unsigned int height DEFAULT_VALUE(400));

Wenn der Benutzer nicht weiß, was er schreiben soll, kann dieser Trick hilfreich sein:

Anwendungsbeispiel

  • Dies war eine C-Frage und die Lösung stellt keine Standardwerte für C bereit. Das Kompilieren Ihres C-Codes als C++ ist nicht wirklich interessant, dann können Sie genauso gut die Standardwerte verwenden, die C++ bereitstellt. Außerdem ist C-Code nicht immer gültiger C++-Code, was einen Portierungsaufwand impliziert.

    – Allan Wind

    8. September 2020 um 11:51 Uhr

Benutzeravatar von unwind
entspannen

Nein.

Nicht einmal der allerneueste C99-Standard unterstützt dies.

  • Dies war eine C-Frage und die Lösung stellt keine Standardwerte für C bereit. Das Kompilieren Ihres C-Codes als C++ ist nicht wirklich interessant, dann können Sie genauso gut die Standardwerte verwenden, die C++ bereitstellt. Außerdem ist C-Code nicht immer gültiger C++-Code, was einen Portierungsaufwand impliziert.

    – Allan Wind

    8. September 2020 um 11:51 Uhr

Benutzeravatar von Alex B
Alex B

Nein, das ist eine Funktion der C++-Sprache.

1427420cookie-checkC-Standardargumente

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

Privacy policy