Ajith C Narayanan
Ajith C Narayanan

Reputation: 616

How printf() function knows the type of its arguments

Consider the following program,

#include <stdio.h>
int main()
{
    char a = 130;
    unsigned char b = 130;

    printf("a = %d\nb = %d\n",a,b);
    return 0;
}

This program will show the following output.

a = -126
b = 130

My question is how printf() function comes to know the type of a is signed and type of b is unsigned to show result like above?

Upvotes: 1

Views: 1458

Answers (4)

Yash
Yash

Reputation: 128

printf() does not know the data type of arguments. It works on format specifier you passed. The data type you are using is char (having range from -128 to +127) and unsigned char (having range from 0 to 255). Your output for a is overflowed after 127. So the output comes to -126.

Upvotes: 1

Raphael D.
Raphael D.

Reputation: 778

The additional arguments to printf() are formatted according to the type specifier. See here for a list of C format specifiers.

https://fr.cppreference.com/w/c/io/fprintf

It's true that one would not expect b to be printed as 130 in your example since you used the %d specifier and not %u. This surprising behavior seems to be explained here.

Format specifier for unsigned char

I hope I got your question well.

Edit: I can not comment Felix Palmen's answer on account on my low reputation. default argument promotion indeed seems to be the key here, but to me the real question here besides the overflow of a is why b is still printed as 130 despite the use of the signed specifier. It can also be explained with default argument promotion but that should be made more precise.

Upvotes: 2

user2371524
user2371524

Reputation:

printf() doesn't know the types, that's why you have to give a correct format string. The prototype for printf() looks like this:

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

So, the only argument with a known type is the first one, the format string.

This also means that any argument passed after that is subject to default argument promotion -- strongly simplified, read it as any integer will be converted to at least int -- or ask google about the term to learn each and every detail ;)

In your example, you have implementation defined behavior:

char a = 130;

If your char could represent 130, that's what you would see in the output of printf(). Promoting the value to int doesn't change the value. You're getting a negative number instead, which means 130 overflowed your char. The result of overflowing a signed integer type during conversion in C is implementation defined, the value you're getting probably means that on you machine, char has 8 bits (so the maximum value is 127) and the signed integer overflow resulted in a wraparound to the negative value range. You can't rely on that behavior!

In short, the negative number is created in this line -- 130 is of type int, assigning it to char converts it and this conversion overflows.

Once your char has the value -126, passing it to printf() just converts it to int, not changing the value.

Upvotes: 5

danglingpointer
danglingpointer

Reputation: 4920

You need to have a look at the definition of printf statement in stdio.h. You already got the answer in comment printf just write the string pointed by format to stdout.

It's variadic function and it use vargas to get all the arguments in variable-length argument list.

You This is from the glibc from the GNU version.

int __printf (const char *format, ...)
{
   va_list arg;
   int done;

   va_start (arg, format);
   done = vfprintf (stdout, format, arg);
   va_end (arg);

   return done;
}

What vfprintf does?

It just writes the string pointed by format to the stream, replacing any format specifier in the same way as printf does, but using the elements in the variable argument list identified by arg instead of additional function arguments.

More information about the vfprintf

Upvotes: 1

Related Questions