Search code examples
cparameterscoding-stylelegacy

Writing C function parameter types after name list, and no type for some parameters


I've read some, to me, peculiar C-code while studying some examples in the book The Unix Programming Environment (1983).

As a curiosity I wanted to find out more about the, let's call it "style". The point of interest here is the line just below int main(argc, argv)

#include <stdio.h>

int main(argc, argv)
     char *argv[];
{
    printf("%s\n", argv[0]);
    return 0;
}

In my investigation I've found that compiling the above code with the flags -Wall -pedantic -ansi works without any warnings, and replacing -ansi with the more recent -std=c99 (or c11, with gcc and cc) only warns about argc defaulting to int.

I perused the old C89 standard trying to find references to this particular way of writing but didn't find anything on my own so I defer to the greater knowledge of the collective.

Hence the question, from when does this esoteric writing stem and possibly why is it still allowed (legacy reasons?)


Solution

  • The old way to do things was to have functions without prototypes. Functions return int by default, and since the function parameter types are unknown at the call site, you better get it right. This frees you from having to maintain header files, but for various reasons, it is no longer recommended.

    // In func.c
    
    // Default to int return
    func(x, y)
        int x;
        int y;
    {
        return x + y;
    }
    
    // In main.c
    
    main(argc, argv)
        int argc;
        char **argv;
    {
        int result = func(2, 3);
    }
    

    This causes problems if you get the function parameter types wrong.

    int result = func(2.0, 3,0); // Wrong, but no compiler error or warning
    

    It was normal to call functions without including the relevant header file. But you need to declare the function return type.

    // This is NOT a function prototype, it just declares the return type.
    double sin();
    
    double one = sin(3.14); // Correct
    double zero = sin(0); // WRONG
    double zero = sin(0.0); // Correct
    

    Old style functions are still allowed by the standard, except the default return type is gone. This allows you to compile old programs. For new programs, the -Wmissing-prototypes option in GCC helps you to avoid using the old style by accident.

    int func(); // Old-style, can take any number of arguments.
    int func(void); // New-style, takes no arguments, is a function prototype.