views:

902

answers:

15

I came across the following function signature and I wondered if this (the ellipsis, or "...") is some kind of polymorphism?

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

Thanks in advance.

+17  A: 

It's a variable argument list.

uniquesnowflake8
+7  A: 

No, that's the "ellipsis" you're seeing there, assuming you're referring to the ... part of the declaration.

Basically it says that this function takes an unknown number of arguments after the first two that are specified there.

The function has to be written in such a way that it knows what to expect, otherwise strange results will ensue.

For other functions that support this, look at the printf function and its variants.

Lasse V. Karlsen
Moreover, the arguments have an unknown type, too. All you get in the function is a pointer to the first argument which you must turn into something useful yourself
Aaron Digulla
+1  A: 

I assume you are referring to the ellipsis (...)? If so this indicates that 0 or more parameters will follow. It is called varargs, defined in stdarg.h

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

printf uses this functionality. Without it you wouldn't be able to keep adding parameters to the end of the function.

Goz
I would suggest removing the "(VS.71)" suffix from the URL, so that it will always link to the latest version of the documentation.
Hosam Aly
fair enough ... i just got the link via a google search :)
Goz
A: 

No, it is a function that is taking variable number of arguments.

Naveen
A: 

That is not technically polymorphism. fcntl takes variable number of arguments & that is the reason for the ... similar to printf function.

msvcyc
+8  A: 

That is a variadic function. See stdarg.h for more details.

Joe Chung
+1 for teaching me a new word.
Gavin Schultz-Ohkubo
+6  A: 

The ... means that you can pass any number of arguments to this function, as other commenters have already mentioned. Since the optional arguments are not typed, the compiler cannot check the types and you can technically pass in any argument of any type.

So does this mean you can use this to implement some kind of polymorphic function? (I.e., a function that performs some operation based on the type of its arguments.)

No.

The reason you cannot do this, is because you cannot at runtime inspect the types of the arguments passed in. The function reading in the variable argument list is expected to already know the types of the optional arguments it is going to receive.

In case of a function that really is supposed to be able to take any number of arguments of any type (i.e., printf), the types of the arguments are passed in via the format string. This means that the caller has to specify the types it is going to pass in at every invocation, removing the benefit of polymorphic functions (that the caller doesn't have to know the types either).

Compare:

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

You have to specify the type before the varargs function can do the right thing, so this gains you nothing.

rix0rrr
+5  A: 

Does C support polymorphism? No, it doesn't.

However there are several libraries, such as Python C API, that implements a rough variant of polymorphism using structs and pointers. Beware that compiler cannot perform appropriate type checking in most cases.

The tecnhique is 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;

Integer and Person get a Type object with appropriate function pointers (e.g. to functions like integer_to_string and person_to_string).

Now just declare a function accepting an Object *:

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

now you can call this function with both an Integer and a Person:

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

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

EDIT

alternatively you can declare i and p as Object *; of course make_int and make_person will allocate space for Integer and Person and do the appropriate cast:

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

NB: I cannot compile these examples rigth now, please doublecheck them.

I came across the following function signature and I wondered if this (the ellipsis, or "...") is some kind of polymorphism?

yes, it is a primitive form of polymorphism. With only one function signature you are able to pass various structures. However the compiler cannot help you with detecting type errors.

dfa
Your function `print` needs to accept an argument of type `void*`, and then you need to explicitly cast it to `Object*` in order for your example to work.
Konrad Rudolph
fixed, thanks Konrad
dfa
-1 because I think it's not really what the original question was about, despite the word "polymorphism" in the title. This answer would be more appropriate for a question: how can we implement polymorphism in C.
John Saunders
A: 

C neither supports function overloading - which is a type of ad-hoc polymorphism based on compile-time types - nor multiple dispatch (ie overloading based on runtime types).

To simulate function overloading in C, you have to create multiple differently named functions. The functions' names often contain the type information, eg fputc() for characters and fputs() for strings.

Multiple dispatch can be implemented by using variadic macros. Again, it's the programmer's job to provide the type information, but this time via an extra argument, which will be evaluated at runtime - in contrast to the compile-time function name in case of the approach given above. The printf() family of functions might not be the best example for multiple dispatch, but I can't think of a better one right now.

Other approaches to multiple dispatch using pointers instead of variadic functions or wrapping values in structures to provide type annotations exist.

Christoph
+3  A: 

Adding to what's been said: C supports polymorphism through other means. For example, take the standard library qsort function which sorts data of arbitrary type.

It is able to do so by means of untyped (void) pointers to the data. It also needs to know the size of the data to sort (provided via sizeof) and the logic that compares the objects' order. This is accomplished by passing a function pointer to the qsort function.

This is a prime example of runtime polymorphism.

There are other ways to implement object-oriented behaviour (in particular, virtual function calls) by managing the virtual function tables manually. This can be done by storing function pointers in structures and passing them around. Many APIs do so, e.g. the WinAPI, which even uses advanced aspects of object orientation, e.g. base class call dispatch (DefWindowProc, to simulate calling the virtual method of the base class).

Konrad Rudolph
-1: Konrad, I think that's a major stretch of the standard definition of polymorphism. It's really nothing more than how to handle untyped data. It's a regression into our dark, untyped past - it's how we used to need to do things before we had OO.
John Saunders
John, sorry but you're wrong and I am right. There's no stretch, there is no such thing as a “standard” definition and the *usual* definition of polymorphism is completely unspecific with regards to the technology used to implement it.
Konrad Rudolph
There are many different forms of polymorphism, not just sub-type polymorphism with inheritance. Parametric polymorphism (templates, for example) and i would say passing a function pointer is parametric polymorphism too, although i'm not too experienced with these terms. Then there is static polymorphism with overloaded functions. I think konrad is right with this.
Johannes Schaub - litb
A: 

The printf declaration in the standard library is

int printf(const char*, ...);

Think about that.

IlDan
A: 

No i dont think there is no concept of opps in c

Nagu
A: 

You can write code that supports Polymorphic behavior in C, but the ... (ellipsis) is not going to be much help. That is for variable arguments to a function.

If you want polymorphic behavior you can use, unions and structures to construct a data structure that has a "type" section and variable fields depending on type. You can also include tables of function pointers in the structures. Poof! You've invented C++.

manovi
A: 

C supports a crude form of Polymorphism. I.e. a type being able to appear and behave as another type. It works in a similar was as in C++ under the hood (relying on memory being aligned) but you have to help the compiler out by casting. E.g. you can define a struct:

typedef struct {
     char forename[20];
     char surname[20];
     } Person;

And then another struct:

    typedef struct {
             char forename[20];
             char surname[20];
             float salary;
             char managername[20];
             } Employee;

Then

int main (int argc, int *argv)
{
    Employee Ben;
    setpersonname((Person *) &Ben);
}

void setpersonname(Person *person)
{
   strcpy((*person).Name,"Ben");
}

The above example shows Employee being used as a Person.

Ben Breen
I still say this is really stretching the terminology. _Yes_ Employee acts like Person, because _everything_ in C acts like a sequence of bytes with some small set of semantics mapped over top of it. You'd just as well say that COMMON blocks in FORTRAN represent polymorphism, or the totally-untyped address space of the system, as accessed by assembler.
John Saunders
Yes it's not compiler supported 'Type Polymorphism', and depending upon the computer science dictionary definition it could be argued one way or another. I guess I was showing the best that C can do.
Ben Breen
Don't forget you could define Employee using a union struct if you're going to do it this way. This enforces the common byte ordering!
maxwellb
A: 

Yes C Do support the polymorphism

the Code which we write in the C++ using virtual to implement the polymorphism if first converted to a C code by Compiler ( one can find details here

http://www.eventhelix.com/RealtimeMantra/basics/object_oriented_programming_in_c.htm

)

its well known that virtual functionality in C++ is implemented using function pointers .

Kumar Vishal