kpagcha
kpagcha

Reputation: 174

Prototype of printf and implementation

I started to wonder how the printf function is declared, it always receive a string as first parameter (well, const char*) and then the rest of the parameters can be a varierty of types, a variable number of them and given in different order.

Does this mean the printf function is declared and overridden for each of the possibilities? This does not make much sense to me, so does it really work like this or it's way different?

Also, how is the function implemented? If it's too complicated I'd just like to know how it works internally in general.

Upvotes: 4

Views: 23079

Answers (4)

Gabriel Staples
Gabriel Staples

Reputation: 53015

Here's a cheesy little program that shows that the prototype for printf is:

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

(and that it doesn't require the restrict keyword as shown by others).

Notice that printf here works withOUT including the otherwise-required stdio.h header file. This is because simply declaring a prototype for the printf function keeps the compiler happy by telling it that this function prototype does indeed exist, and since the object code for the definition (implementation) of printf also happens to exist elsewhere, the linker is happy at the time of linking, after compilation.

Notice the extern "C" {} thing required for C++, however, to prevent the C++ compiler from name-mangling the function name. See the comments above the code for all compile commands I used and tested. Also note that the printing of the "true" stuff is just for kicks, as I was testing some stuff out.

hello_world.c:

/*
hello_world

Gabriel Staples
www.ElectricRCAircraftGuy.com
27 Mar. 2019 

Examples of how to compile & run:
- NB: c90 requires C-style comments (slash star, star slash) and does NOT work with modern
      C++-style // comments!
  C:
    gcc -Wall -o hello_world hello_world.c && ./hello_world
    gcc -Wall -std=c90 -o hello_world hello_world.c && ./hello_world
    gcc -Wall -std=c99 -o hello_world hello_world.c && ./hello_world
    gcc -Wall -std=c11 -o hello_world hello_world.c && ./hello_world
  C++:
    g++ -Wall -o hello_world hello_world.c && ./hello_world
    g++ -Wall -std=c++98 -o hello_world hello_world.c && ./hello_world
    g++ -Wall -std=c++03 -o hello_world hello_world.c && ./hello_world
    g++ -Wall -std=c++11 -o hello_world hello_world.c && ./hello_world


*/

// #include <stdio.h>   // for printf
#include <stdbool.h> // for `true` and `false`

#ifdef __cplusplus
extern "C" {
#endif
int printf ( const char * format, ... ); // a hacky alternative to including stdio.h above! 
#ifdef __cplusplus
}
#endif

int main(void)
{
    printf("Hello World\n");
    printf("`true == 1`? = %i, `true == 1`? = %s\n", true, (true == 1 ? "true" : "false"));

    return 0;
}

Sample output:

$ gcc -Wall -o hello_world hello_world.c && ./hello_world
Hello World
`true == 1`? = 1, `true == 1`? = true

Upvotes: 0

Shafik Yaghmour
Shafik Yaghmour

Reputation: 158569

how the printf function is declared

printf is a variadic function and it declared since C99 as follows:

​int printf( const char *restrict format, ... );
                                         ^^^

The ... or ellipses indicate that there are a variable number of argument and we would use the va_start, va_arg, va_end macros and va_list type to access the arguments.

how is the function implemented?

and example of a very simple printf is given in the document linked above is as follows and modified to work in C:

#include <stdio.h>
#include <stdarg.h>

void simple_printf(const char *fmt, ...)
{
    va_list args;
    va_start(args, fmt);

    while (*fmt != '\0') {
        if (*fmt == 'd') {
            int i = va_arg(args, int);
            printf( "%d\n", i ) ;
        } else if (*fmt == 'c') {
            int c = va_arg(args, int);
            printf( "%c\n", (char)c ) ;
        } else if (*fmt == 'f') {
            double d = va_arg(args, double);
            printf( "%f\n", d ) ;
        }
        ++fmt;
    }

    va_end(args);
}

int main()
{
    simple_printf("dcff", 3, 'a', 1.999, 42.5); 
}

Upvotes: 6

haccks
haccks

Reputation: 106092

Each standard library has corresponding header containing the function prototype for all the functions in that library and definitions of various data types and constants that needed by the functions. The header for printf is <stdio.h> which includes its prototype

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

Upvotes: 0

Yu Hao
Yu Hao

Reputation: 122463

The prototype of printf is:

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

This feature (the argument ...) is called variable arguments functions. You can do it as well with the help of stdarg.h.

Here's a start: C FAQ: Variable-Length Argument Lists

Upvotes: 0

Related Questions