C Type Casting

Type casting in C means converting a value from one type to another. Sometimes C does this automatically, and sometimes you write an explicit cast so the compiler knows exactly what conversion you want. Casting matters because the type of an expression controls the calculation, the stored result, and whether information is preserved or lost.

Overview: How Type Casting Works

C is statically typed, but expressions are not locked to only one type forever. When you combine values, assign a value, pass an argument, or write a cast, C may convert a value to another type. For example, assigning an int to a double converts the integer value into a floating-point value. Assigning a double to an int converts the value the other way, but the fractional part is discarded.

There are two broad categories. An implicit conversion happens automatically because the language rules require it. An explicit cast is written by the programmer using a type name in parentheses, such as (double)count. Explicit casts are useful when you need to choose the type used in an expression, especially with division. They are also a signal to readers that a conversion is intentional.

Under the hood, a cast does not usually change the original object in memory. It produces a converted value for that expression. If int n = 7; and you calculate (double)n / 2, n is still an int. C creates a double value from n for that calculation, then performs floating-point division.

C also performs integer promotions and usual arithmetic conversions. Small integer types such as char and short are commonly promoted to int before arithmetic. When an int and a double appear in the same arithmetic expression, the int is converted to double so both operands have a common type. These automatic conversions are convenient, but they can hide mistakes if you do not know they are happening.

Not every conversion is equally safe. Widening conversions, such as int to double or float to double, usually preserve the value for ordinary beginner examples. Narrowing conversions, such as double to int or long to short, can discard fractions, change values that are too large, or produce implementation-defined results. Treat casts as tools, not as a way to silence warnings without understanding the conversion.

Syntax

int whole = (int)3.9;
double exact = (double)7 / 2;
char letter = (char)65;
unsigned int flags = (unsigned int)whole;
Part Meaning
(int)3.9 Converts the value 3.9 to int, discarding the fractional part.
(double)7 / 2 Converts 7 before division, so the operation uses floating-point division.
(char)65 Converts the integer value to a character value on the current character set.
(unsigned int)whole Converts an integer expression to an unsigned integer type.

The cast operator has high precedence, so (double)7 / 2 means convert 7 first, then divide. This is different from (double)(7 / 2), which performs integer division first and converts the already-truncated result afterward.

Examples

Fixing Integer Division

#include <stdio.h>

int main(void)
{
    int apples = 7;
    int people = 2;

    double without_cast = apples / people;
    double with_cast = (double)apples / people;

    printf("Without cast: %.2f\n", without_cast);
    printf("With cast: %.2f\n", with_cast);

    return 0;
}

Output:

Without cast: 3.00
With cast: 3.50

The first division uses two int operands, so C performs integer division and produces 3. That integer result is then converted to double for storage in without_cast. In the second calculation, apples is converted before the division, so C uses floating-point division and keeps the fractional part.

Converting a Decimal Amount to Cents

#include <stdio.h>

int main(void)
{
    double price = 19.99;
    int cents = (int)(price * 100 + 0.5);
    int dollars = cents / 100;
    int remaining_cents = cents % 100;

    printf("Price: $%.2f\n", price);
    printf("Cents: %d\n", cents);
    printf("Dollars: %d\n", dollars);
    printf("Remaining cents: %d\n", remaining_cents);

    return 0;
}

Output:

Price: $19.99
Cents: 1999
Dollars: 19
Remaining cents: 99

This example converts a floating-point price into an integer number of cents. Multiplying by 100 moves the decimal point, adding 0.5 performs simple rounding for positive values, and casting to int drops the remaining fraction. Real financial software usually stores money as integers from the beginning, but this shows how a deliberate conversion can prepare a value for integer arithmetic.

Casting Between Character and Integer Values

#include <stdio.h>

int main(void)
{
    int code = 66;
    char initial = (char)code;
    int next_code = (int)initial + 1;
    char next_initial = (char)next_code;

    printf("Initial: %c\n", initial);
    printf("Code: %d\n", (int)initial);
    printf("Next code: %d\n", next_code);
    printf("Next initial: %c\n", next_initial);

    return 0;
}

Output:

Initial: B
Code: 66
Next code: 67
Next initial: C

A char is an integer type, so it can participate in numeric conversions. On ASCII-compatible systems, code 66 represents 'B' and 67 represents 'C'. The casts make the intended interpretation clear, although portable programs should be careful about assuming exact numeric character codes outside common ASCII-compatible environments.

How It Works Step by Step

  1. The compiler first determines the type of each operand in an expression.
  2. For many arithmetic operations, small integer types are promoted to int and mixed numeric types are converted to a common type.
  3. If you wrote an explicit cast, that conversion is applied to the cast expression before the surrounding operation uses it.
  4. The operation is performed using the resulting operand types. Two integers divide as integers; a floating-point operand makes division floating point.
  5. If the final value is stored in a variable of another type, assignment conversion happens again.

For double result = (double)completed / total;, the cast converts completed to double. Then total is also converted to double by the usual arithmetic conversions. The division produces a double, which is stored in result without losing the fractional part.

For int whole = (int)3.9;, the floating-point value is converted to an integer. C truncates toward zero, so 3.9 becomes 3 and -3.9 would become -3. This is truncation, not rounding. If you need rounding, you must write that logic or use library functions in later lessons.

Common Mistakes

Casting After Integer Division

A cast must happen before the operation that needs the new type. Casting the result of integer division is too late.

#include <stdio.h>

int main(void)
{
    int completed = 5;
    int total = 8;

    double wrong = (double)(completed / total);
    double correct = (double)completed / total;

    printf("Wrong: %.2f\n", wrong);
    printf("Correct: %.2f\n", correct);

    return 0;
}

Output:

Wrong: 0.00
Correct: 0.62

completed / total is 0 because both operands are integers. The wrong version converts that 0 to 0.0. The correct version converts completed first, so the division keeps the decimal part.

Expecting a Cast to Change the Original Variable

A cast creates a converted value for the current expression. It does not change the declared type or stored value of the variable being cast.

#include <stdio.h>

int main(void)
{
    int count = 9;
    double half = (double)count / 2;

    printf("Count: %d\n", count);
    printf("Half: %.1f\n", half);

    return 0;
}

Output:

Count: 9
Half: 4.5

The variable count remains an int with the value 9. Only the value used in the division was converted to double.

Using Casts to Hide Warnings

If a compiler warns about a conversion, do not add a cast automatically. First ask what information may be lost. Converting double to int discards the fractional part, and converting a large value to a smaller integer type may not produce the value you expect.

Best Practices

  • Cast before division when you need a floating-point result from integer values.
  • Prefer changing variable types over adding many casts when the value is naturally decimal throughout the program.
  • Use casts to document intentional conversions, not to silence warnings you have not investigated.
  • Be careful with narrowing conversions because they can lose fractions or exceed the target type’s range.
  • Remember that (int)x truncates toward zero; it does not round to the nearest integer.
  • Keep casts close to the value being converted so the expression is easy to read.
  • Compile with warnings such as -Wall -Wextra to catch suspicious implicit conversions.

Practice Exercises

  1. Write a program with int earned = 17; and int possible = 20;. Print the score as a decimal ratio using a cast.
  2. Create a double temperature such as 98.6, convert it to an int, and print both values. Explain what happened to the decimal part.
  3. Store the integer code 65, cast it to char, and print both the numeric value and character value.

Summary

  • Type casting converts a value from one type to another.
  • Implicit conversions happen automatically; explicit casts use syntax such as (double)value.
  • A cast affects the value in an expression, not the original variable’s declared type.
  • Casting before integer division is a common way to get a decimal result.
  • Converting floating-point values to integers truncates toward zero.
  • Narrowing conversions can lose information, so use them deliberately.
  • Compiler warnings are useful clues about conversions that deserve attention.