2010-06-07 2 views
14

Conversione di una lib di C++ in ANSI C e sembra che ANSI C non supporti i valori predefiniti per le variabili di funzione o sono errato? Quello che voglio è qualcosa di simile aValori predefiniti sugli argomenti nelle funzioni C e sovraccarico delle funzioni in C

int funcName(int foo, bar* = NULL); 

Inoltre, sta sovraccaricando possibile funzione in ANSI C?

avrebbe bisogno

const char* foo_property(foo_t* /* this */, int /* property_number*/); 

const char* foo_property(foo_t* /* this */, const char* /* key */, int /* iter */); 

potrebbe naturalmente solo il nome in modo diverso, ma viene utilizzato per C++ I kinda usato per funzionare sovraccarico.

+3

No, non supporta nessuno di questi. – Artefacto

risposta

21

No, anche C standard non supporta. Perché pensi di aver bisogno di convertire il tuo codice C++ in C? Potrebbe essere piuttosto complicato - avrei pensato che scrivere wrapper sarebbe la strada da percorrere, se il tuo C++ deve essere richiamabile da C.

+0

Ora sto lavorando in un ambiente C e l'uso del codice C++ è stato bannato;) ... Quindi, invece di rendere il C compatibile esistente con il compilatore g ++ e quindi essere in grado di usare le classi C++ insieme al codice C I ' m costretto a convertire le classi utili esistenti devo C. – inquam

+2

@ inchiesta: no. Usa la lingua a portata di mano, non provare a forzare qualche altra lingua nella gola del compilatore. Mentre è comparativamente facile far funzionare il codice C in un ambiente C++, l'opposto è tutt'altro che banale (come hai appena capito). Piuttosto, ri-implementa le tue "classi utili" come una libreria di funzioni C piuttosto che provare a "port" su 1: 1. – DevSolar

+0

@inquam In generale, sono d'accordo con DevSolar. In particolare se si sono utilizzate funzionalità C++ come contenitori di librerie standard, eccezioni e in particolare RAII. Tuttavia, se il tuo codice originale ha semplicemente il C++ come "una C migliore", allora credo che sia praticamente fattibile, anche se non vorrei essere colui che lo fa. –

1

Né dei valori predefiniti o sovraccarico di funzioni esiste in ANSI C, quindi avrai per risolverlo in un modo diverso.

3

Per quanto ne so ANSI C non supporta direttamente l'overloading delle funzioni o gli argomenti predefiniti. Il sostituto standard per il sovraccarico sta aggiungendo i suffissi al nome della funzione che indica i tipi di argomento. Ad esempio, in OpenGL, un suffisso "3fv" per un nome di funzione significa che la funzione accetta un vettore di tre float.

Gli argomenti predefiniti possono essere visualizzati come un caso speciale di sovraccarico di funzione.

1

Non è possibile così facilmente poiché C non li supporta. Il modo più semplice per ottenere "sovraccarico falso" sta usando i suffissi come già detto ... i valori predefiniti possono essere simulati usando la funzione degli argomenti variabili, specificando il numero di argomenti passati e assegnando a livello di programmazione quello mancante, ad esempio:

aType aFunction(int nargs, ...) 
{ 
    // "initialization" code and vars 
    switch(nargs) 
    { 
    case 0: 
     // all to default values... e.g. 
     aVar1 = 5; // ... 
     break; 
    case 1: 
     aVar1 = va_arg(arglist, int); //... 
     // initialize aVar2, 3, ... to defaults... 
     break; 
    // ... 
    } 
} 

Anche l'overloading può essere simulato utilizzando var args con informazioni aggiuntive da aggiungere e passare ed extracode ... in pratica riproducendo un runtime minimalista orientato agli oggetti ... Un'altra soluzione (o addirittura la stessa ma con approccio diverso) potrebbe essere tag: ogni argomento è un argomento tipo coppia + argomento (un'unione sull'insieme del tipo di argomento possibile), c'è un tag di terminazione speciale (non è necessario specificare quanti argomenti stai passando) e ovviamente hai sempre bisogno di " collaborazione "da la funzione che stai chiamando, cioè deve contenere codice aggiuntivo per analizzare i tag e scegliere la funzione effettiva da fare (si comporta come una sorta di dispatcher)

0

Dovrai dichiarare ogni funzione sovraccaricata C++ in modo diverso in C perché C non fa name mangling. Nel tuo caso "foo_property1" "foo_property2".

15

Tuttavia ho trovato un "trucco" per farlo se si utilizza GCC.

GCC ha un'estensione ## comoda sulla macro variadic che consente di simulare un argomento predefinito.

Il trucco ha limitazioni: funziona solo per 1 valore predefinito e l'argomento deve essere l'ultimo dei parametri di funzione.

Ecco un esempio funzionante.

#include <stdio.h> 


#define SUM(a,...) sum(a, (5, ##__VA_ARGS__)) 

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


main() 
{ 

    printf("%d\n", SUM(3, 7)); 

    printf("%d\n", SUM(3)); 

} 

In questo caso, definisco SUM come una chiamata per riassumere con il secondo argomento default è 5.

Se si chiama con 2 argomenti (prima chiamata in main), sarebbe preelaborato come: sum (3, (5, 7));

Ciò significa:

  • 1 argomento è 3
  • secondo argomento è il risultato della sequenza (5, 7) che è ... ovviamente 7!

Poiché gcc è intelligente, questo non ha alcun effetto sul runtime in quanto il primo membro della sequenza è una costante e non è necessario, verrà semplicemente scartato in fase di compilazione.

Se si chiama con un solo argomento, l'estensione gcc rimuoverà il VA_ARGS E il coma principale. Quindi è preelaborato come:

somma (3, (5));

quindi il programma dà i risultati attesi:

10 
8 

Quindi, ciò non perfettamente simulare (con usuali limitazioni macro) una funzione con 2 argomenti, l'ultima delle quali è facoltativo con un valore predefinito applicata se non fornito.

4

C'è un modo per supportare quanti parametri predefiniti sono necessari, basta usare una struttura.

// Populate structure with var list and set any default values 
struct FooVars { 
    int int_Var1 = 1; // One is the default value 
    char char_Command[2] = {"+"}; 
    float float_Var2 = 10.5; 
}; 
struct FooVars MainStruct; 

//... 
// Switch out any values needed, leave the rest alone 
MainStruct.float_Var2 = 22.8; 
Myfunc(MainStruct); // Call the function which at this point will add 1 to 22.8. 
//... 

void Myfunc(struct FooVars *MyFoo) { 
    switch(MyFoo.char_Command) { 
    case '+': 
     printf("Result is %i %c %f.1 = %f\n" MyFoo.int_Var1, MyFoo.char_Command, MyFoo.float_Var2, (MyFoo.float_Var2 + MyFoo.int_Var1); 
     break; 
    case '*': 
     // Insert multiply here, you get the point... 
     break; 
    case '//': 
     // Insert divide here... 
     break; 
    } 
} 
+3

Non sono esperto C, ma non è possibile impostare valori predefiniti in una struttura come quella. Puoi? – user1863152

2

Prova questo.

#include <stdio.h> 
#include <stdarg.h> 

/* print all non-negative args one at a time; 
    all args are assumed to be of int type */ 
void printargs(int arg1, ...) 
{ 
    va_list ap; 
    int i; 

    va_start(ap, arg1); 
    for (i = arg1; i >= 0; i = va_arg(ap, int)) 
    printf("%d ", i); 
    va_end(ap); 
    putchar('\n'); 
} 

int main(void) 
{ 
    printargs(5, 2, 14, 84, 97, 15, 24, 48, -1); 
    printargs(84, 51, -1); 
    printargs(-1); 
    printargs(1, -1); 
    return 

0; 
} 
-1

Credo u possibile utilizzare una funzione con argomenti variabili qui è il mio esempio

#include <stdarg.h> 
#include <stdio.h> 
void baz(int flag, ...) 
{ 
    va_list ap; 
    char *bar = "baz"; /* default value */ 
    va_start(ap, flag); 
    if (flag == 1) 
     bar = va_arg(ap, char *); 
    va_end(ap); 
    printf("%s\n", bar); 
} 
int main(void) 
{ 
    baz(0); 
    baz(1, "foo"); 
    baz(2); 
    baz(1, "bar"); 
    return 0; 
} 

l'uscita è

baz 
foo 
baz 
bar 

se u guardare per esempio l'uomo 2 aperta dicono

SYNOPSIS 
     #include <sys/types.h> 
     #include <sys/stat.h> 
     #include <fcntl.h> 

     int open(const char *pathname, int flags); 
     int open(const char *pathname, int flags, mode_t mode); 

     int creat(const char *pathname, mode_t mode); 

     int openat(int dirfd, const char *pathname, int flags); 
     int openat(int dirfd, const char *pathname, int flags, mode_t mode); 

ma mod e in realtà è un ... argomento