C Standardargumente

279

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

Nathaniel Flath
quelle
6
Ich möchte nur ein etwas besseres C, nicht C ++. denke C +. mit einer Vielzahl von kleinen Verbesserungen aus C ++, aber nicht das große Durcheinander. Und bitte keinen anderen Linkloader. sollte nur ein weiterer präprozessorähnlicher Schritt sein. standardisiert. überall ...
ivo Welch
Verwandte Frage , die ich nicht in der Seitenleiste gesehen habe.
Shelby Moore III
Ich würde sagen, hör auf, Barbar zu sein und lerne, C ++ (11, ...) gut zu benutzen - jk! / Ich lösche Flammen ... aber ... du wirst es lieben ... hahaha, ich kann mir nicht helfen, sorry.
Moodboom

Antworten:

147

Nicht wirklich. Die einzige Möglichkeit wäre , eine varargs-Funktion zu schreiben und Standardwerte für Argumente, die der Aufrufer nicht übergibt, manuell einzugeben .

Eli Courtwright
quelle
22
Ich hasse die mangelnde Überprüfung bei der Verwendung von Varargs.
dmckee --- Ex-Moderator Kätzchen
16
Das solltest du auch; Ich empfehle das eigentlich nicht; Ich wollte nur vermitteln, dass es möglich ist.
Eli Courtwright
4
Wie möchten Sie jedoch überprüfen, ob der Anrufer das Argument übergibt oder nicht? Ich denke, damit das funktioniert, haben Sie nicht den Anrufer, der Ihnen sagt, dass er es nicht bestanden hat? Ich denke, dies macht den gesamten Ansatz etwas weniger benutzerfreundlich - der Aufrufer könnte auch eine Funktion mit einem anderen Namen aufrufen.
Johannes Schaub - litb
3
Der open(2)Systemaufruf verwendet dies für ein optionales Argument, das abhängig von den erforderlichen Argumenten vorhanden sein kann, und printf(3)liest eine Formatzeichenfolge, die angibt, wie viele Argumente vorhanden sein werden. Beide verwenden Varargs ziemlich sicher und effektiv, und obwohl man sie sicherlich vermasseln kann, printf()scheint sie besonders beliebt zu sein.
Chris Lutz
4
@Eli: Nicht alle C-Compiler sind gcc. Es gibt einige fortgeschrittene Compiler-Magie, die warnt, wenn Ihre printf () - Argumente nicht mit Ihrer Formatzeichenfolge übereinstimmen. Und ich denke nicht, dass es möglich ist, ähnliche Warnungen für Ihre eigenen variadischen Funktionen zu erhalten (es sei denn, sie verwenden den gleichen Stil der Formatzeichenfolge).
Tomlogic
280

Wow, hier ist jeder 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. In meiner Arbeit habe ich eine Reihe von Makros, um all dies zu automatisieren. Sobald Sie den Ablauf verstanden haben, fällt es Ihnen leicht, dasselbe zu tun.

Ich habe dies an anderer Stelle geschrieben. Hier ist ein detaillierter externer Link, der die Zusammenfassung hier ergänzt: http://modelingwithdata.org/arch/00000022.htm

Wir möchten uns umdrehen

double f(int i, double x)

in eine Funktion, die Standardeinstellungen ü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 Standardeinstellungen 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 variadischen Makros von C verwenden. Auf diese Weise müssen Benutzer nicht wissen, dass sie tatsächlich eine f_argsStruktur füllen, und denken, dass sie das Übliche tun:

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

OK, jetzt würde alles 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, wie zusammengesetzte Initialisierer Standardeinstellungen für die genauen Regeln festlegen.

Eine Sache, die nicht funktioniert: f(0)weil wir nicht zwischen einem fehlenden Wert und Null unterscheiden können. Nach meiner Erfahrung ist dies etwas, auf das Sie achten müssen, das Sie jedoch bei Bedarf erledigen können - die Hälfte der Zeit, in der Ihr Standardwert wirklich Null ist.

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

bk.
quelle
16
+1 kreativ! Es hat seine Grenzen, bringt aber auch benannte Parameter in die Tabelle. Beachten Sie, dass {}(leerer Initialisierer) ein Fehler C99 ist.
u0b34a0f6ae
28
Hier ist jedoch etwas Großartiges für Sie: Der Standard ermöglicht die mehrfache Angabe benannter Mitglieder, die spätere Überschreibung. Nur für benannte Parameter können Sie das Standardproblem lösen und einen leeren Aufruf zulassen. #define vrange(...) CALL(range,(param){.from=1, .to=100, .step=1, __VA_ARGS__})
u0b34a0f6ae
3
Ich hoffe, die Compilerfehler sind lesbar, aber das ist eine großartige Technik! Sieht fast aus wie Python Kwargs.
Zwei
6
@ RunHolt Obwohl sicherlich einfacher, ist es objektiv nicht besser; Die genannten Parameter bieten Vorteile wie die einfache Lesbarkeit von Aufrufen (auf Kosten der Lesbarkeit des Quellcodes). Eines ist besser für Entwickler der Quelle, das andere ist besser für Benutzer der Funktion. Es ist ein wenig voreilig, einfach "dieser ist besser!"
Alice
3
@DawidPi: C11 6.7.9 (19) zum Initialisieren von Aggregaten: "Alle Unterobjekte, die nicht explizit initialisiert werden, müssen implizit genauso initialisiert werden wie Objekte mit statischer Speicherdauer." Und wie Sie wissen, werden Elemente mit statischer Dauer auf Null initialisiert | NULL | \ 0. [Dies war auch in c99.]
bk.
161

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 können Sie mit C keine Methoden überladen, sodass Sie am Ende zwei verschiedene Funktionen haben. Wenn Sie jedoch f2 aufrufen, rufen Sie tatsächlich f1 mit einem Standardwert auf. Dies ist eine "Wiederholen Sie sich nicht" -Lösung, mit der Sie vermeiden können, vorhandenen Code zu kopieren / einzufügen.

Wim zehn Brink
quelle
24
FWIW, ich würde es vorziehen, die Zahl am Ende der Funktion zu verwenden, um die Anzahl der benötigten Argumente anzugeben. Erleichtert die Verwendung einer beliebigen Zahl. :)
Macke
4
Dies ist bei weitem die beste Antwort, da sie einen einfachen Weg zeigt, um 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 verpasst habe (ich habe nicht mehr an den Standardparameter gedacht!)
RunHolt
4
f2 könnte auch ein Präprozessor-Makro sein
osvein
41

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 Standard-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
u0b34a0f6ae
quelle
2
Dies scheint eine einfachere und einfachere Implementierung zu sein als die Wim ten Brink- oder BK-Lösung. Gibt es Nachteile dieser Implementierung, die die anderen nicht auch besitzen?
Stephen
24

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

toriningen
quelle
19

Nein.

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

entspannen
quelle
ein einfaches Nein wäre noch besser gewesen;)
KevinDTimm
21
@kevindtimm: Das ist nicht möglich, SO schreibt eine Mindestlänge für Antworten vor. Ich habe es versucht. :)
Entspannen Sie sich
2
Bitte beziehen Sie sich auf meine Antwort. :)
Chaos
18

Nein, das ist eine C ++ - Sprachfunktion.

Alex B.
quelle
14

Kurze Antwort: Nein.

Etwas längere Antwort: Es gibt eine alte, alte Problemumgehung, bei der Sie eine Zeichenfolge übergeben, die Sie nach optionalen Argumenten analysieren :

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

Dabei kann opt ein Paar "Name = Wert" oder etwas anderes enthalten, das Sie gerne aufrufen würden

n = f(2,3.0,"foo","plot=yes save=no");

Offensichtlich ist dies nur gelegentlich nützlich. Im Allgemeinen, wenn Sie eine einzelne Schnittstelle zu einer Funktionsfamilie wünschen.


Sie finden diesen Ansatz immer noch in Teilchenphysik-Codes, die von professionellen Programmen in C ++ (wie zum Beispiel ROOT ) geschrieben wurden. Der Hauptvorteil besteht darin, dass es nahezu unbegrenzt verlängert werden kann, während die Rückenkompatibilität erhalten bleibt.

dmckee --- Ex-Moderator Kätzchen
quelle
2
Kombiniere dies mit Varargs und du hast jede Menge Spaß!
David Thornley
5
Ich würde eine benutzerdefinierte verwenden structund den Anrufer eine erstellen lassen, die Felder für verschiedene Optionen ausfüllen und sie dann als Adresse übergeben oder NULLals Standardoptionen übergeben.
Chris Lutz
Das Kopieren von Codemustern von ROOT ist eine schreckliche Idee!
Innisfree
13

Der wahrscheinlich beste Weg, dies zu tun (was in Ihrem Fall je nach Ihrer Situation möglich oder nicht möglich ist), besteht darin, zu C ++ zu wechseln und es als "besseres C" zu verwenden. Sie können C ++ verwenden, ohne Klassen, Vorlagen, Operatorüberladung oder andere erweiterte Funktionen zu verwenden.

Dadurch erhalten Sie eine Variante von C mit Funktionsüberladung und Standardparametern (und allen anderen Funktionen, die Sie verwendet haben). Sie müssen nur ein wenig diszipliniert sein, wenn Sie es wirklich ernst meinen, nur eine eingeschränkte Teilmenge von C ++ zu verwenden.

Viele Leute werden sagen, dass es eine schreckliche Idee ist, C ++ auf diese Weise zu verwenden, und sie könnten einen Punkt haben. Aber es ist nur eine Meinung; Ich denke, es ist gültig, Funktionen von C ++ zu verwenden, mit denen Sie vertraut sind, ohne sich auf das Ganze einlassen zu müssen. Ich denke, ein wesentlicher Grund für den Erfolg von C ++ ist, dass es in den Anfängen von sehr vielen Programmierern genau auf diese Weise verwendet wurde.

Michael Burr
quelle
13

Eine weitere Option verwendet structs:

struct func_opts {
  int    arg1;
  char * arg2;
  int    arg3;
};

void func(int arg, struct func_opts *opts)
{
    int arg1 = 0, arg3 = 0;
    char *arg2 = "Default";
    if(opts)
      {
        if(opts->arg1)
            arg1 = opts->arg1;
        if(opts->arg2)
            arg2 = opts->arg2;
        if(opts->arg3)
            arg3 = opts->arg3;
      }
    // do stuff
}

// call with defaults
func(3, NULL);

// also call with defaults
struct func_opts opts = {0};
func(3, &opts);

// set some arguments
opts.arg3 = 3;
opts.arg2 = "Yes";
func(3, &opts);
Chris Lutz
quelle
9

Nein.

Chaos
quelle
2
Was ist die Problemumgehung? Ich kann sehen, dass es 20202020hexadezimal ist, aber wie schreibe ich es?
Lazer
5

Ein weiterer Trick mit Makros:

#include <stdio.h>

#define func(...) FUNC(__VA_ARGS__, 15, 0)
#define FUNC(a, b, ...) func(a, b)

int (func)(int a, int b)
{
    return a + b;
}

int main(void)
{
    printf("%d\n", func(1));
    printf("%d\n", func(1, 2));
    return 0;
}

Wenn nur ein Argument übergeben wird, wird bder Standardwert empfangen (in diesem Fall 15).

David Ranieri
quelle
4

Nein, aber Sie können eine Reihe von Funktionen (oder Makros) verwenden, um die Standardargumente zu verwenden:

// No default args
int foo3(int a, int b, int c)
{
    return ...;
}

// Default 3rd arg
int foo2(int a, int b)
{
    return foo3(a, b, 0);  // default c
}

// Default 2nd and 3rd args
int foo1(int a)
{
    return foo3(a, 1, 0);  // default b and c
}
David R Tribble
quelle
4

Ja, mit den Funktionen von C99 können Sie dies tun. Dies funktioniert ohne Definition neuer Datenstrukturen oder so und ohne dass die Funktion zur Laufzeit entscheiden muss, wie sie aufgerufen wurde, und ohne Rechenaufwand.

Eine ausführliche Erklärung finden Sie in meinem Beitrag unter

http://gustedt.wordpress.com/2010/06/03/default-arguments-for-c99/

Jens

Jens Gustedt
quelle
Sehen Sie auch meine Antwort, die von Ihrer abgeleitet ist.
Shelby Moore III
1
Inline ein Beispiel.
user877329
3

Im Allgemeinen nein, aber in gcc Sie können den letzten Parameter von funcA () mit einem Makro optional machen.

In funcB () verwende ich einen speziellen Wert (-1), um zu signalisieren, dass ich den Standardwert für den Parameter 'b' benötige.

#include <stdio.h> 

int funcA( int a, int b, ... ){ return a+b; }
#define funcA( a, ... ) funcA( a, ##__VA_ARGS__, 8 ) 


int funcB( int a, int b ){
  if( b == -1 ) b = 8;
  return a+b;
}

int main(void){
  printf("funcA(1,2): %i\n", funcA(1,2) );
  printf("funcA(1):   %i\n", funcA(1)   );

  printf("funcB(1, 2): %i\n", funcB(1, 2) );
  printf("funcB(1,-1): %i\n", funcB(1,-1) );
}
Sambowry
quelle
1

Ich habe Jens Gustedts Antwort so verbessert , dass:

  1. Inline-Funktionen werden nicht verwendet
  2. Die Standardeinstellungen werden während der Vorverarbeitung berechnet
  3. modulare wiederverwendbare Makros
  4. Es ist möglich, einen Compilerfehler festzulegen, der dem Fall unzureichender Argumente für die zulässigen Standardeinstellungen entspricht
  5. Die Standardeinstellungen müssen nicht das Ende der Parameterliste bilden, wenn die Argumenttypen eindeutig bleiben
  6. Interopts mit C11 _Generic
  7. Variieren Sie den Funktionsnamen durch die Anzahl der Argumente!

variadic.h:

#ifndef VARIADIC

#define _NARG2(_0, _1, _2, ...) _2
#define NUMARG2(...) _NARG2(__VA_ARGS__, 2, 1, 0)
#define _NARG3(_0, _1, _2, _3, ...) _3
#define NUMARG3(...) _NARG3(__VA_ARGS__, 3, 2, 1, 0)
#define _NARG4(_0, _1, _2, _3, _4, ...) _4
#define NUMARG4(...) _NARG4(__VA_ARGS__, 4, 3, 2, 1, 0)
#define _NARG5(_0, _1, _2, _3, _4, _5, ...) _5
#define NUMARG5(...) _NARG5(__VA_ARGS__, 5, 4, 3, 2, 1, 0)
#define _NARG6(_0, _1, _2, _3, _4, _5, _6, ...) _6
#define NUMARG6(...) _NARG6(__VA_ARGS__, 6, 5, 4, 3, 2, 1, 0)
#define _NARG7(_0, _1, _2, _3, _4, _5, _6, _7, ...) _7
#define NUMARG7(...) _NARG7(__VA_ARGS__, 7, 6, 5, 4, 3, 2, 1, 0)
#define _NARG8(_0, _1, _2, _3, _4, _5, _6, _7, _8, ...) _8
#define NUMARG8(...) _NARG8(__VA_ARGS__, 8, 7, 6, 5, 4, 3, 2, 1, 0)
#define _NARG9(_0, _1, _2, _3, _4, _5, _6, _7, _8, _9, ...) _9
#define NUMARG9(...) _NARG9(__VA_ARGS__, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0)
#define __VARIADIC(name, num_args, ...) name ## _ ## num_args (__VA_ARGS__)
#define _VARIADIC(name, num_args, ...) name (__VARIADIC(name, num_args, __VA_ARGS__))
#define VARIADIC(name, num_args, ...) _VARIADIC(name, num_args, __VA_ARGS__)
#define VARIADIC2(name, num_args, ...) __VARIADIC(name, num_args, __VA_ARGS__)

// Vary function name by number of arguments supplied
#define VARIADIC_NAME(name, num_args) name ## _ ## num_args ## _name ()
#define NVARIADIC(name, num_args, ...) _VARIADIC(VARIADIC_NAME(name, num_args), num_args, __VA_ARGS__)

#endif

Vereinfachtes Nutzungsszenario:

const uint32*
uint32_frombytes(uint32* out, const uint8* in, size_t bytes);

/*
The output buffer defaults to NULL if not provided.
*/

#include "variadic.h"

#define uint32_frombytes_2(   b, c) NULL, b, c
#define uint32_frombytes_3(a, b, c)    a, b, c
#define uint32_frombytes(...) VARIADIC(uint32_frombytes, NUMARG3(__VA_ARGS__), __VA_ARGS__)

Und mit _Generic:

const uint8*
uint16_tobytes(const uint16* in, uint8* out, size_t bytes);

const uint16*
uint16_frombytes(uint16* out, const uint8* in, size_t bytes);

const uint8*
uint32_tobytes(const uint32* in, uint8* out, size_t bytes);

const uint32*
uint32_frombytes(uint32* out, const uint8* in, size_t bytes);

/*
The output buffer defaults to NULL if not provided.
Generic function name supported on the non-uint8 type, except where said type
is unavailable because the argument for output buffer was not provided.
*/

#include "variadic.h"

#define   uint16_tobytes_2(a,    c) a, NULL, c
#define   uint16_tobytes_3(a, b, c) a,    b, c
#define   uint16_tobytes(...) VARIADIC(  uint16_tobytes, NUMARG3(__VA_ARGS__), __VA_ARGS__)

#define uint16_frombytes_2(   b, c) NULL, b, c
#define uint16_frombytes_3(a, b, c)    a, b, c
#define uint16_frombytes(...) VARIADIC(uint16_frombytes, NUMARG3(__VA_ARGS__), __VA_ARGS__)

#define   uint32_tobytes_2(a,    c) a, NULL, c
#define   uint32_tobytes_3(a, b, c) a,    b, c
#define   uint32_tobytes(...) VARIADIC(  uint32_tobytes, NUMARG3(__VA_ARGS__), __VA_ARGS__)

#define uint32_frombytes_2(   b, c) NULL, b, c
#define uint32_frombytes_3(a, b, c)    a, b, c
#define uint32_frombytes(...) VARIADIC(uint32_frombytes, NUMARG3(__VA_ARGS__), __VA_ARGS__)

#define   tobytes(a, ...) _Generic((a),                                                                                                 \
                                   const uint16*: uint16_tobytes,                                                                       \
                                   const uint32*: uint32_tobytes)  (VARIADIC2(  uint32_tobytes, NUMARG3(a, __VA_ARGS__), a, __VA_ARGS__))

#define frombytes(a, ...) _Generic((a),                                                                                                 \
                                         uint16*: uint16_frombytes,                                                                     \
                                         uint32*: uint32_frombytes)(VARIADIC2(uint32_frombytes, NUMARG3(a, __VA_ARGS__), a, __VA_ARGS__))

Und mit variadischer Funktionsnamenauswahl, die nicht mit _Generic kombiniert werden kann:

// winternitz() with 5 arguments is replaced with merkle_lamport() on those 5 arguments.

#define   merkle_lamport_5(a, b, c, d, e) a, b, c, d, e
#define   winternitz_7(a, b, c, d, e, f, g) a, b, c, d, e, f, g
#define   winternitz_5_name() merkle_lamport
#define   winternitz_7_name() winternitz
#define   winternitz(...) NVARIADIC(winternitz, NUMARG7(__VA_ARGS__), __VA_ARGS__)
Shelby Moore III
quelle
1

JA

Durch Makros

3 Parameter:

#define my_func2(...) my_func3(__VA_ARGS__, 0.5)
#define my_func1(...) my_func2(__VA_ARGS__, 10)
#define VAR_FUNC(_1, _2, _3, NAME, ...) NAME
#define my_func(...) VAR_FUNC(__VA_ARGS__, my_func3, my_func2, my_func1)(__VA_ARGS__)

void my_func3(char a, int b, float c) // b=10, c=0.5
{
    printf("a=%c; b=%d; c=%f\n", a, b, c);
}

Wenn Sie das 4. Argument möchten, muss ein zusätzliches my_func3 hinzugefügt werden. Beachten Sie die Änderungen in VAR_FUNC, my_func2 und my_func

4 Parameter:

#define my_func3(...) my_func4(__VA_ARGS__, "default") // <== New function added
#define my_func2(...) my_func3(__VA_ARGS__, (float)1/2)
#define my_func1(...) my_func2(__VA_ARGS__, 10)
#define VAR_FUNC(_1, _2, _3, _4, NAME, ...) NAME
#define my_func(...) VAR_FUNC(__VA_ARGS__, my_func4, my_func3, my_func2, my_func1)(__VA_ARGS__)

void my_func4(char a, int b, float c, const char* d) // b=10, c=0.5, d="default"
{
    printf("a=%c; b=%d; c=%f; d=%s\n", a, b, c, d);
}

Einzige Ausnahme, dass Float- Variablen keine Standardwerte zugewiesen werden können ( es sei denn, es handelt sich um das letzte Argument wie im Fall mit 3 Parametern ), da sie einen Punkt ('.') Benötigen, der in Makroargumenten nicht akzeptiert wird. Kann aber eine Problemumgehung finden, wie im Makro my_func2 ( Fall mit 4 Parametern) zu sehen )

Programm

int main(void)
{
    my_func('a');
    my_func('b', 20);
    my_func('c', 200, 10.5);
    my_func('d', 2000, 100.5, "hello");

    return 0;
}

Ausgabe:

a=a; b=10; c=0.500000; d=default                                                                                                                                                  
a=b; b=20; c=0.500000; d=default                                                                                                                                                  
a=c; b=200; c=10.500000; d=default                                                                                                                                                
a=d; b=2000; c=100.500000; d=hello  
Ramu
quelle
0

Ja, Sie können etwas Simulaires tun. Hier müssen Sie die verschiedenen Argumentlisten kennen, die Sie erhalten können, aber Sie haben dieselbe Funktion wie alle anderen.

typedef enum { my_input_set1 = 0, my_input_set2, my_input_set3} INPUT_SET;

typedef struct{
    INPUT_SET type;
    char* text;
} input_set1;

typedef struct{
    INPUT_SET type;
    char* text;
    int var;
} input_set2;

typedef struct{
    INPUT_SET type;
    int text;
} input_set3;

typedef union
{
    INPUT_SET type;
    input_set1 set1;
    input_set2 set2;
    input_set3 set3;
} MY_INPUT;

void my_func(MY_INPUT input)
{
    switch(input.type)
    {
        case my_input_set1:
        break;
        case my_input_set2:
        break;
        case my_input_set3:
        break;
        default:
        // unknown input
        break;
    }
}
eaanon01
quelle
-6

Warum können wir das nicht tun?

Geben Sie dem optionalen Argument einen Standardwert. Auf diese Weise muss der Aufrufer der Funktion nicht unbedingt den Wert des Arguments übergeben. Das Argument nimmt den Standardwert an. Und leicht wird dieses Argument für den Kunden optional.

Zum Beispiel

void foo (int a, int b = 0);

Hier ist b ein optionales Argument.

Navgupta
quelle
10
Erstaunliche Erkenntnisse, das Problem ist, dass C keine optionalen Argumente oder überladenen Funktionen unterstützt, sodass die direkte Lösung nicht kompiliert werden kann.
Thomas