Reputation: 174
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
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
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
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
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