¿Qué significa … en una lista de argumentos en C?

6 minutos de lectura

avatar de usuario
Anónimo

Encontré la siguiente firma de función y me preguntaba si esto (los puntos suspensivos o "...") es algún tipo de polimorfismo?

#include <fcntl.h>
int fcntl(int fd, int cmd, ... );

Gracias por adelantado.

  • Pregunta bastante justa. +1. Algunas personas todavía piensan que las preguntas simples no son adecuadas, a pesar de las indicaciones de los poderes fácticos de que lo son.

    – pax diablo

    14 de julio de 2009 a las 9:12

  • Sugeriría cambiar el título de la pregunta a “¿Qué son los puntos suspensivos (…) en C?”

    – Hosam Ali

    14 de julio de 2009 a las 9:26

  • @Hosam: Sí, no se trata realmente de polimorfismo… Título cambiado.

    – Dave Sheroman

    14 de julio de 2009 a las 10:05

  • @Dave Sherohman: Tampoco se trata de puntos suspensivos.

    – Anónimo

    14 de julio de 2009 a las 10:07

  • Lo que está claro es que viste los puntos suspensivos y pensaste que significaba polimorfismo. no lo hace Una segunda pregunta podría ser: “Dado que los puntos suspensivos no significan polimorfismo, ¿hay otra forma de obtenerlo?”. Esa sería una pregunta aparte.

    – John Saunders

    14 de julio de 2009 a las 10:55

Es un lista de argumentos variables.

Eso es un función variádica. Ver stdarg.h para más detalles.

los ... significa que puede pasar cualquier número de argumentos a esta función, como ya han mencionado otros comentaristas. Dado que los argumentos opcionales no se escriben, el compilador no puede verificar los tipos y técnicamente puede pasar cualquier argumento de cualquier tipo.

Entonces, ¿esto significa que puede usar esto para implementar algún tipo de función polimórfica? (Es decir, una función que realiza alguna operación basada en el tipo de sus argumentos).

No.

La razón por la que no puede hacer esto es porque no puede inspeccionar en tiempo de ejecución los tipos de argumentos pasados. Se espera que la función que lee en la lista de argumentos variables ya conozca los tipos de argumentos opcionales que va a recibir.

En el caso de una función que realmente se supone que puede tomar cualquier número de argumentos de cualquier tipo (es decir, printf), los tipos de los argumentos se pasan a través de la cadena de formato. Esto significa que la persona que llama tiene que especificar los tipos que va a pasar en cada invocación, eliminando el beneficio de las funciones polimórficas (que la persona que llama tampoco tiene que conocer los tipos).

Comparar:

// Ideal invocation
x = multiply(number_a, number_b)
y = multiply(matrix_a, matrix_b)

// Standard C invocation
x = multiply_number(number_a, number_b)
y = multiply_matrix(matrix_a, matrix_b)

// Simulated "polymorphism" with varargs
x = multiply(T_NUMBER, number_a, number_b)
y = multiply(T_MATRIX, matrix_a, matrix_b)

Debe especificar el tipo antes de que la función varargs pueda hacer lo correcto, por lo que esto no le aporta nada.

avatar de usuario
Lasse V. Karlsen

No, esa es la “puntos suspensivos” que está viendo allí, suponiendo que se esté refiriendo a la ... parte de la declaración.

Básicamente dice que esta función toma un número desconocido de argumentos después de los dos primeros que se especifican allí.

La función debe escribirse de tal manera que sepa qué esperar, de lo contrario, se producirán resultados extraños.

Para otras funciones que soportan esto, mire el printf función y sus variantes.

avatar de usuario
DFA

¿C admite polimorfismo? No, no lo hace.

Sin embargo, hay varias bibliotecas, como Python C API, que implementa una variante aproximada de polimorfismo utilizando estructuras y punteros. Tenga en cuenta que el compilador no puede realizar la comprobación de tipos adecuada en la mayoría de los casos.

La técnica es simple:

typedef struct {
    char * (*to_string)();
} Type;

#define OBJ_HEADER Type *ob_type

typedef struct {
    OBJ_HEADER;
}  Object; 

typedef struct {
    OBJ_HEADER;
    long ival;        
} Integer;

typedef struct {
    OBJ_HEADER;
    char *name;
    char *surname;
} Person;

Entero y Persona obtienen un objeto Tipo con punteros de función apropiados (por ejemplo, a funciones como entero_a_cadena y persona_a_cadena).

Ahora simplemente declare una función que acepte un Objeto *:

void print(Object *obj) {
    printf("%s", obj->type->to_string());
}

ahora puede llamar a esta función tanto con un número entero como con una persona:

Integer *i = make_int(10);
print((Object *) i);

Person *p = make_person("dfa");
print((Object *) p);

EDITAR

alternativamente, puede declarar i y p como Object *; por supuesto, make_int y make_person asignarán espacio para Integer y Person y realizarán la conversión adecuada:

Object * 
make_integer(long i) {
     Integer *ob = malloc(sizeof(Integer));
     ob->ob_type = &integer_type;
     ob->ival = i;
     return (Object *) ob;
}

NB: No puedo compilar estos ejemplos en este momento, verifíquelos dos veces.

Encontré la siguiente firma de función y me preguntaba si esto (los puntos suspensivos o “…”) es algún tipo de polimorfismo.

si, es un forma primitiva de polimorfismo. Con solo una firma de función, puede pasar varias estructuras. Sin embargo, el compilador no puede ayudarlo a detectar errores de tipo.

  • tu funcion print necesita aceptar un argumento de tipo void*y luego necesitas lanzarlo explícitamente a Object* para que tu ejemplo funcione.

    – Konrad Rodolfo

    14 de julio de 2009 a las 10:04

  • -1 porque creo que no se trata realmente de la pregunta original, a pesar de la palabra “polimorfismo” en el título. Esta respuesta sería más apropiada para una pregunta: ¿cómo podemos implementar el polimorfismo en C.

    – John Saunders

    14 de julio de 2009 a las 11:05

avatar de usuario
Konrad Rodolfo

Agregando a lo que se ha dicho: C admite el polimorfismo a través de otros medios. Por ejemplo, tome la biblioteca estándar qsort función que ordena datos de tipo arbitrario.

Es capaz de hacerlo por medio de untyped (void) punteros a los datos. También necesita saber el tamaño de los datos para ordenar (proporcionado a través de sizeof) y la lógica que compara el orden de los objetos. Esto se logra pasando un puntero de función al qsort función.

Este es un excelente ejemplo de polimorfismo en tiempo de ejecución.

Hay otras formas de implementar el comportamiento orientado a objetos (en particular, llamadas a funciones virtuales) administrando las tablas de funciones virtuales manualmente. Esto se puede hacer almacenando punteros de función en estructuras y pasándolos. Muchas API lo hacen, por ejemplo, WinAPI, que incluso utiliza aspectos avanzados de orientación a objetos, por ejemplo, envío de llamadas de clase base (DefWindowProcpara simular llamar al método virtual de la clase base).

  • tu funcion print necesita aceptar un argumento de tipo void*y luego necesitas lanzarlo explícitamente a Object* para que tu ejemplo funcione.

    – Konrad Rodolfo

    14 de julio de 2009 a las 10:04

  • -1 porque creo que no se trata realmente de la pregunta original, a pesar de la palabra “polimorfismo” en el título. Esta respuesta sería más apropiada para una pregunta: ¿cómo podemos implementar el polimorfismo en C.

    – John Saunders

    14 de julio de 2009 a las 11:05

Supongo que te refieres a los puntos suspensivos (…)? Si es así, esto indica que seguirán 0 o más parámetros. Se llama varargs, definido en stdarg.h

http://msdn.microsoft.com/en-us/library/kb57fad8.aspx

printf usa esta funcionalidad. Sin él, no podría seguir agregando parámetros al final de la función.

  • Sugeriría eliminar el sufijo “(VS.71)” de la URL, para que siempre se vincule a la última versión de la documentación.

    – Hosam Ali

    14 de julio de 2009 a las 9:28

¿Ha sido útil esta solución?

Esta web utiliza cookies propias y de terceros para su correcto funcionamiento y para fines analíticos y para mostrarte publicidad relacionada con sus preferencias en base a un perfil elaborado a partir de tus hábitos de navegación. Al hacer clic en el botón Aceptar, acepta el uso de estas tecnologías y el procesamiento de tus datos para estos propósitos. Configurar y más información
Privacidad