2010-06-07 13 views
14

Convirtiendo una lib de C++ en ANSI C y parece que ANSI C no admite valores predeterminados para variables de función o ¿me equivoco? Lo que quiero es algo así comoValores predeterminados en argumentos en funciones C y sobrecarga de funciones en C

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

Además, está sobrecargando posible función en ANSI C?

necesitaría

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

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

Podría, por supuesto, sólo el nombre de manera diferente, pero que se utiliza para C++ yo un poco acostumbrado a la sobrecarga de funciones.

+3

No, no admite nada de eso. – Artefacto

Respuesta

21

No, la norma C tampoco es compatible. ¿Por qué siente que necesita convertir su código C++ a C? Eso podría ser bastante complicado. Pensaría que escribir envoltorios sería el camino a seguir, si su C++ debe ser invocable desde C.

+0

Ahora estoy trabajando en un entorno C y el uso del código C++ ha sido prohibido;) ... Así que en lugar de hacer que el C existente cumpla con el compilador g ++ y así poder usar clases C++ junto con el código C I ' m forzado a convertir clases útiles existentes Tengo que C. – inquam

+2

@ inquam: No. Usa el lenguaje que tienes a mano, no intentes forzar a otro idioma a bajar la garganta del compilador. Si bien es relativamente fácil hacer que el código C funcione en un entorno C++, lo contrario es cualquier cosa menos trivial (como se acaba de dar cuenta). Más bien, vuelva a implementar sus "clases útiles" como una biblioteca de funciones en C, en lugar de intentar "portarlas" en 1: 1. – DevSolar

+0

@inquam En general, estoy de acuerdo con DevSolar. Particularmente si ha utilizado alguna característica de C++, como contenedores de la Biblioteca estándar, excepciones y particularmente RAII. Sin embargo, si su código original simplemente utiliza C++ como "una C mejor", entonces supongo que es casi factible, aunque no me gustaría ser quien lo haga. –

1

Ninguno de los valores predeterminados o la sobrecarga de funciones existe en ANSI C, por lo que tendrá para resolverlo de una manera diferente.

3

Por lo que sé, ANSI C no admite directamente la sobrecarga de funciones ni los argumentos predeterminados. El sustituto estándar de la sobrecarga es agregar sufijos al nombre de la función que indica los tipos de argumento. Por ejemplo, en OpenGL, un sufijo "3fv" para un nombre de función significa que la función toma un vector de tres flotantes.

Los argumentos predeterminados se pueden ver como un caso especial de sobrecarga de funciones.

1

No puede hacerlo tan fácilmente ya que C no los admite. La forma más simple de obtener "sobrecarga falsa" es usar sufijos como ya se dijo ... los valores predeterminados podrían simularse usando la función de argumentos variables, especificando el número de args pasados, y programáticamente dando el valor por defecto, por ejemplo:

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

También se puede simular la sobrecarga usando var args con información adicional para ser añadida y pasada y extracódigo ... básicamente reproduciendo un tiempo de ejecución orientado a objetos minimalista ... Otra solución (o la misma pero con diferente enfoque) podría estar usando tags: cada argumento es un argumento de par tipo + argumento (una unión en todo el conjunto de posibles tipos de argumentos), hay una etiqueta de terminador especial (no es necesario especificar cuántos argumentos estás pasando) y, por supuesto, siempre necesitas " colaboración "de la función que está llamando, es decir, debe contener código adicional para analizar las etiquetas y elegir la función real que se realizará (se comporta como un tipo de despachador)

0

Deberá declarar cada función sobrecargada de C++ de forma diferente en C porque C no hace name mangling. En su caso "foo_property1" "foo_property2".

15

Sin embargo, encontré un "truco" para hacerlo si usa GCC.

GCC tiene una práctica extensión ## en variadic macro que le permite simular un argumento predeterminado.

El truco tiene sus limitaciones: funciona solo para 1 valor predeterminado, y el argumento debe ser el último de los parámetros de la función.

Aquí hay un ejemplo de trabajo.

#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)); 

} 

En este caso, defino SUM como una llamada a la suma con el segundo argumento predeterminado es 5.

Si llama con 2 argumentos (primera llamada en main), sería preprocesado como: sum (3, (5, 7));

Esto significa:

  • primera argumento es 3
  • segundo argumento es el resultado de la secuencia (5, 7) ... que es, obviamente, 7!

Como gcc es inteligente, esto no tiene efecto en el tiempo de ejecución ya que el primer miembro de la secuencia es una constante y no es necesario, simplemente se descartará en tiempo de compilación.

Si llama con un solo argumento, la extensión gcc eliminará VA_ARGS Y coma principal. Entonces es preprocesado como:

suma (3, (5));

Así, el programa da el resultado esperado:

10 
8 

Por lo tanto, esto perfectamente simular (con las limitaciones macro habituales) una función con 2 argumentos, siendo la última opcional con un valor por defecto se aplica si no se previsto.

4

Hay una manera de admitir tantos parámetros predeterminados que necesita, simplemente use una estructura.

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

No soy un experto en C, pero no puede establecer valores predeterminados en una estructura como esa. ¿Puedes? – user1863152

2

Pruebe esto.

#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

Creo que u puede utilizar una función con argumentos variables aquí es mi ejemplo

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

la salida es

baz 
foo 
baz 
bar 

si u look por ejemplo el hombre 2 abierta dicen

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); 

pero mod e es en realidad un ... argumento