Implicit Type Conversion or “ITC” is a technique used by C (and many other programming languages) compilers to bring maximum compatibility to variables and data types. Using ITC, when you make a relation between two different data types, compiler will do its best to implicitly convert one data type to another. (In this case, you can think of “Implicitly” as “Automatically”.)

For a better understanding, see the following simple example code:

const float pi = 3.1415 ; char var = 0 , i = 2 ; var = pi + i ;

As you can see in the third line, The integer-only-value of the “char var” has been set to a float value. In such cases, ITC will convert the float value of pi to char value and help your code to run without any trouble.

Sometimes, ITC will act as more than just a “trouble killer”. As you’ve likely used it as the main solution to implement some logics!

printf(“

Enter a number here: “) ; float number = 0.0 ; scanf(“%f” , &number); long int numberChecker = number //ITC is the key here. if (numberChecker == number) printf(“%ld is integer

” , numberChecker); else printf(“%f is float

” , number) ;

There is no doubt that ITC is massively helpful. But it doesn’t mean you can be confident of data type conversions. The very first reason is ITC’s inability to perform conversion on every data type. For example, It can’t convert a string pointer (explicitly: pointer to a char array) containing an integer value to int data type. So, if you are going to make a command line tool, you can’t count on ITC to convert input strings (such as argv[] pointers) to numbers. Because Implicit Type Conversion won’t occur in such cases.

Notes for beginners : 1-You may not count on argv[0] pointer too. it often represents the name of your program. 2-You can use stdlib.h functions to convert such data types. In this case, you can use atoi() in order to convert a string pointer to integer.

Using Inappropriate Format Specifiers:

Inappropriate use of format specifiers may lead to dangerous conditions. We know that logging is an extremely helpful technique to find out what’s wrong with our code. Even with the features of today’s fancy debuggers, in some cases logging is the best tool available. But what if our logs lie? Now, test this:

float i = 20.5 ; printf(“%d”, i); // prints: 1606416520

But why? Because ITC won’t occur when you use incompatible format specifier. As the digital representation of float and int values is different, the function will read the binary representation of i variable with integer representation rules (explicitly: Two’s complement notation) in mind. And as it turns out, it will give you a perfectly wrong report.

Another example:

unsigned char i = 200 ; //Supported Range: 0 — 255 printf(“%hhd” , i) ;// prints: -56

Why? The reason is exactly the same. %hhd is suitable for signed char data types. The notation of unsigned char is extremely simple. It simply is the decimal value in base 2. But notation of signed values is sightly different (Two’s complement notation will be used). So when function reads the base 2 value with 2's complement notation in mind, it will give out a wrong value.

Another example:

//just kidding ☺

So, let’s take a look at the most essential format specifiers and their usage:

%d or %i => signed integer values (suitable for int , usable for char) %hhd => signed char (numerical) %hhu => unsigned char (numerical) %c => signed char (characterical) %f => float and double values %Lf => long double values %g => double (automatic) %e => double (scientific notation) %zu => size_t values (sizeof() operator)

Quick note: It’s good to know that you can customize %f, %i, %d, %g & %e format specifiers. Add l before d or i or L before g, e or f (such as %ld or %Lf) to make them suitable for long types. You can also add u before i or d to make them suitable for unsigned types. (There’s a lot more to know about format specifiers. you can keep learning on here. This tutorial is also recommended for a more beginner guide)

Setting the value of variables directly from the const values:

In an overall grouping, C data types are divided into 2 main groups: float and integer. Integer variables are grouped to char & int data types. float and double data types are belonged to the float Variables. When you’re going to assign const values directly to a variable, you may consider this groupings.

When you are assigning a value to integer variables, you must consider the signed/unsigned state of your value. If you don’t, in real world (code!), you maybe faced by really confusing conditions, because of previously described different notation and representation issue.

In the case of assigning values to float variables, you can use type specification technique which is using special f and L specifiers to indicate whether the const value is float or long double, in order to prevent implicit type conversion.

float pi = 3.1415926535f double pi = 3.1415926535 //if you don’t use any specifier, compiler will assume const value as double long double pi = 3.1415926535L

Note that if you don’t use these specifiers, ITC will occur. It’s the least dangerous state of ITC. So, you can even forget these specifiers and let ITC do the job for you. But wait! Unlikely, There might be a very similar condition that is very dangerous. Look at the following example:

float n1 = 3.1415; if (n1 == 3.1415) { printf(“Hello”); // Sorry! Already dead code }

Try it. It won’t print out any “Hello”! The cause is: when you compare two float values in C, ITC will not occur. In the above code, n1 is float but as I said before, the 3.1415 const value is assumed as double. the precision of double and float value is different. So they can’t be evaluated as “equal”.

‌Compiler Warnings:

The behind-the-scene-ness of ITC can be very confusing. You can search your compiler options to activate implicit type conversion warnings. This warnings will help you to know where ITC happened and look for probable problems. If your IDE/Compiler doesn’t provide any ITC warning, you must code precisely to avoid ITC related side effects and problems.