Question

I have a question about default argument promotions in C99 standard. In the book "C Programming - A Modern Approach, 2nd Edition" I've read that:

Argument Conversions:

[...]

1) The compiler has encountered a prototype prior to the call. [...]

2) The compiler has not encountered a prototype prior to the call. The compiler performs the default argument promotions: (1)floatarguments are converted todouble. (2) The integral promotions are performed, causingcharandshortarguments to be converted toint. (In C99, the integer promotions are performed.)

A few lines further is shown an example in which there is no function prototype or definition before calling it. It is commented as follows:

Of course, a much better solution is to provide a prototype forsquarebefore calling it. In C99, callingsquarewithout first providing a declaration or definition of the function is an error.

Aren't those two cursive sentences kind of contrary with each other? I mean, if C99 forbids calling functions without previous declaration/definition how can it determine promotions in that kind of function call?

Was it helpful?

Solution

No they are not contradictory.

A declaration is not necessarily a prototype:

int f();

declares the function f but isn't a prototype since nothing is known about the argument types.

int (a)
 in a;
{
 ...
}

is a definition but isn't a prototype either.

OTHER TIPS

C99 does not forbid you to call functions that have no prototype.

I can't give the details because you have not posted code for square() or the call to it, but presumably what is happening is that the promotion made to the arguments in the call to square() result in different types being passed to the function than it actually declares in the implementation.

That's what would result in undefined behavior, and would be an error.

For example:

// in foo.c:

int foo(void)
{ 
    char x = 42;

    return square(x); // x is promoted to int, but is wrong
}


// in bar.c

#include <stdio.h>
void bar(int x)
{ 
    square( &x); // this call is fine -  what is being passed is what square() expects
    printf("The result is %d\n", x);
}


// in square.c

void square( int* p)
{
    *p *= *p;
    return;
}

And if square() is defined with a prototype that declares the parameter to have an argument of type char, there's no way to call correctly it without a prototype having been 'seen' by the calling code since in such cases the argument will be promoted to int.

I cannot find anything about it being an error of calling a function without providing a prior declaration or definition in C99.

The closes thing seems to be that the default return type of int is no longer assumed. i.e. the declaration foo(int a); is allowed pre-C99, but an error in C99. pre-C99 it'd mean int foo(int a);

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top