I'm just wondering why am I getting a 0 value when I try to print the addition of a char
and an integer value. My code is as follows:
int y;
y = 10;
char z;
z = '9';
printf("%f", z y);
CodePudding user response:
This call of printf
printf("%f", z y);
invokes undefined behavior because you are using the incorrect conversion specifier %f
with an object of the type int.
You need to cast the argument like for example
printf( "%f", ( double )( z y ) );
or
printf( "%f", ( float )( z y ) );
though in the last case the argument will be promoted to the type double due to the default argument promotions.
CodePudding user response:
Most of the time, when you call a function, and you pass the wrong type of argument, C automatically converts it for you. For example, if I write
#include <math.h>
int i = sqrt(144);
printf("%d\n", i);
this works, and prints 12
. It works even though the sqrt
function actually wants an argument of type double
— because the compiler knows that, and automatically converts my int
argument 144
to double
before passing it to sqrt
. (There's also a conversion on the way back, because sqrt
returns a double
, which has to be converted back to int
before assigning to i
.)
But the printf
function itself is a big, giant exception to this rule. In your code, you had
printf("%f", z y);
Now, you and I both know that %f
wants a double
, but this is not something that, traditionally, the C language can know about. As far as the C language is concerned, the printf
function takes one argument of type const char *
(that is, a string), and then possibly some number of other arguments, depending on the particular %
-sequences that are found in the format string at run-time. So the compiler makes only a half-hearted attempt, converting them to a few, common types and then passing them on to printf
to do the rest. In your example, since z
is a char
and y
is an int
, z y
will be an int
, and that's what gets passed to printf
. By the time printf
is chewing on the format string and finds the format specifier %f
, it has no way of knowing what type of argument was actually passed, so it can't even try to do any conversions of its own. All it can do is assume that you actually passed a double
— and, since you didn't, you get a meaningless value printed instead.
Now, although as I've just explained, the compiler didn't traditionally have any license to try to convert printf
arguments to the proper type, modern compilers typically do take a peek at the format string, if they can, and check that things are going to work properly at run time. For example, when I run your code through one of my compilers, I get warning: format specifies type 'double' but the argument has type 'int'
. If your compiler is not giving you warnings like this, you might want to find out if there's a way to enable them, because they're obviously super handy.
CodePudding user response:
As already pointed out in the comments section, it is your responsibility to ensure that the format string and the function arguments match. In your case, they do not match. The result of the expression z y
is of type int
, but you are using the %f
conversion specifier in the format string, which is only valid for the data types float
and double
(float
gets promoted to double
).
As pointed out in the comments section, you have two options to fix this:
- change the format string to expect an argument of type
int
, or - cast the argument to
double
orfloat
The solution using option #1 would look like this:
Change the line
printf("%f", z y);
to
printf("%d", z y);
The solution using option #2 would look like this:
Change the line
printf("%f", z y);
to
printf("%f", (double) (z y) );