How to tell, in C, if parameters to a function are provided?

Viewed 173

In C, when you declare a function without parameters, that function can accept any number of parameters. Example:

int sum() {
  // some code
}

int subs(void) {
  // some code
}

int main() {
    sum(1, 2, 3, 4, 5, 6); // This is valid
    subs(1, 2, 3, 4, 5, 6); // This is NOT valid
}

How to tell, in the first case(sum), if some parameters are provided?

Thanks in advance

3 Answers

How to tell, in C, if parameters to a function are provided?

It's not possible. From C perspective there is no possibility to know if any arguments are provided to such function nor what their count is.

when you declare a function without parameters, that function can accept any number of parameters

Yes, when you declare a function without parameters. And it does not necessarily means the function accepts any number of parameters. In the code you presented:

int sum() {
  // some code
}

it's the sum function definition. In a definition, when the function has no parameters, then, well, the function really really has no parameters - it's as if int sum(void). It's from C11 6.7.6.3p14, emphasis mine:

An identifier list declares only the identifiers of the parameters of the function. An empty list in a function declarator that is part of a definition of that function specifies that the function has no parameters. The empty list in a function declarator that is not part of a definition of that function specifies that no information about the number or types of the parameters is supplied.

The code you presented is invalid - sum takes no parameters.

So:

sum(1, 2, 3, 4, 5, 6); // This is also NOT valid

As a workaround you can pass a reference to the array with types information and references to variables.

typedef enum
{
    CHAR_T,
    INT_T,
    FLOAT_T,
}TYPES_t;


typedef struct
{
    TYPES_t type;
    void *arg;
}ARG_t;



int foo(ARG_t *args)
{
    size_t argnum = 0;

    while(args -> arg)
    {
        printf("Parameter %zu has type pointer to ", argnum);
        switch(args -> type)
        {
            case CHAR_T:
                printf("char and value of the refenced object is %c\n", *(char *)args -> arg);
                break;
            case INT_T:
                printf("int and value of the refenced object is %d\n", *(int *)args -> arg);
                break;
            case FLOAT_T:
                printf("float and value of the refenced object is %f\n", *(float *)args -> arg);
                break;
        }
        args++;
    }
}


int main(void)
{
    int i = 1234;
    char c = 'c';
    float f = 9876.543;
    ARG_t args[10] = {{CHAR_T, &c}, {INT_T, &i}, {FLOAT_T, &f}, {0,}};

    foo(args);
}

The way you tell is to read the documentation for the function being called.

The caller is responsible for passing arguments that are acceptable to the function being called.

This is true not just for the number of parameters but for their values. For example, a function named SquareRoot might be specified to return the square root of a non-negative value it is passed but to have undefined behavior if a negative value is passed. In this case, the caller is responsible for passing a non-negative value.

So we see that declaring function parameters and having the compiler report errors in the numbers or types of arguments is just a part of the task of ensuring functions are called correctly.

Related