Coming Soon

This lesson is currently being developed

Introduction to type conversion and static_cast

Learn about converting between different data types.

Fundamental Data Types
Chapter
Beginner
Difficulty
40min
Estimated Time

What to Expect

Comprehensive explanations with practical examples

Interactive coding exercises to practice concepts

Knowledge quiz to test your understanding

Step-by-step guidance for beginners

Development Status

In Progress

Content is being carefully crafted to provide the best learning experience

Preview

Early Preview Content

This content is still being developed and may change before publication.

4.12 — Introduction to type conversion and static_cast

In this lesson, you'll learn about converting between different data types, understand implicit and explicit conversions, and discover how to use static_cast for safe type conversions.

What is type conversion?

Type conversion (also called type casting) is the process of converting a value from one data type to another. This happens when you need to use a value of one type where another type is expected.

Think of type conversion like translating between languages - sometimes the translation is automatic and natural, other times you need to be explicit about what you want to say.

Why do we need type conversions?

Type conversions are necessary because:

  • Different data types have different ranges and precisions
  • Functions may require specific parameter types
  • Mathematical operations between different types need a common type
  • You may need to extract parts of data (like the integer part of a decimal)
#include <iostream>

int main()
{
    std::cout << "Why type conversion is needed:\n\n";
    
    int wholeNumber = 42;
    double decimal = 3.14;
    
    // These operations need type conversion to work
    double result1 = wholeNumber + decimal;  // int converted to double
    int result2 = wholeNumber + decimal;     // double converted to int (loses precision)
    
    std::cout << "wholeNumber + decimal (as double): " << result1 << std::endl;
    std::cout << "wholeNumber + decimal (as int): " << result2 << std::endl;
    
    // Function parameter conversion
    std::cout << "Square root of int: " << std::sqrt(wholeNumber) << std::endl;  // int -> double
    
    return 0;
}

Output:

Why type conversion is needed:

wholeNumber + decimal (as double): 45.14
wholeNumber + decimal (as int): 45
Square root of int: 6.48074

Implicit type conversion (automatic)

Implicit conversion happens automatically when the compiler can safely convert one type to another:

#include <iostream>

int main()
{
    std::cout << "Implicit type conversions:\n\n";
    
    // Widening conversions (safe - no data loss)
    int smallInt = 100;
    long bigInt = smallInt;           // int → long
    double decimal = smallInt;        // int → double
    
    std::cout << "Original int: " << smallInt << std::endl;
    std::cout << "As long: " << bigInt << std::endl;
    std::cout << "As double: " << decimal << std::endl;
    
    // Mixed arithmetic causes implicit conversion
    int intValue = 10;
    double doubleValue = 3.5;
    
    double mixedResult = intValue * doubleValue;  // int promoted to double
    
    std::cout << "\nMixed arithmetic:\n";
    std::cout << intValue << " * " << doubleValue << " = " << mixedResult << std::endl;
    
    // Character to integer conversion
    char letter = 'A';
    int asciiValue = letter;          // char → int (shows ASCII value)
    
    std::cout << "\nCharacter conversion:\n";
    std::cout << "Character '" << letter << "' as int: " << asciiValue << std::endl;
    
    return 0;
}

Output:

Implicit type conversions:

Original int: 100
As long: 100
As double: 100

Mixed arithmetic:
10 * 3.5 = 35

Character conversion:
Character 'A' as int: 65

Implicit conversion problems

Some implicit conversions can cause problems:

#include <iostream>

int main()
{
    std::cout << "Problematic implicit conversions:\n\n";
    
    // Narrowing conversions (data loss)
    double preciseValue = 3.14159;
    int truncatedValue = preciseValue;  // Loses fractional part
    
    std::cout << "Original double: " << preciseValue << std::endl;
    std::cout << "After conversion to int: " << truncatedValue << std::endl;
    
    // Large values in smaller types
    long bigNumber = 2147483648L;  // Larger than int can hold
    int smallerNumber = bigNumber; // May overflow or truncate
    
    std::cout << "\nLarge number conversion:\n";
    std::cout << "Original long: " << bigNumber << std::endl;
    std::cout << "As int: " << smallerNumber << " (may be wrong due to overflow)\n";
    
    // Signed/unsigned conversion
    int negativeValue = -1;
    unsigned int positiveValue = negativeValue;  // Dangerous!
    
    std::cout << "\nSigned to unsigned:\n";
    std::cout << "Negative int: " << negativeValue << std::endl;
    std::cout << "As unsigned: " << positiveValue << " (wraps around!)\n";
    
    return 0;
}

Output:

Problematic implicit conversions:

Original double: 3.14159
After conversion to int: 3

Large number conversion:
Original long: 2147483648
As int: -2147483648 (may be wrong due to overflow)

Signed to unsigned:
Negative int: -1
As unsigned: 4294967295 (wraps around!)

Explicit type conversion with static_cast

Explicit conversion using static_cast makes type conversions obvious and intentional:

Basic static_cast syntax

static_cast<target_type>(value)

Using static_cast safely

#include <iostream>

int main()
{
    std::cout << "Explicit conversion with static_cast:\n\n";
    
    // Safe conversions
    double decimal = 3.14159;
    int wholeNumber = static_cast<int>(decimal);  // Explicit truncation
    
    std::cout << "Double: " << decimal << std::endl;
    std::cout << "Explicitly converted to int: " << wholeNumber << std::endl;
    
    // Character conversions
    int asciiCode = 65;
    char character = static_cast<char>(asciiCode);
    
    std::cout << "\nASCII " << asciiCode << " as character: '" << character << "'\n";
    
    // Arithmetic with specific precision
    int numerator = 7;
    int denominator = 3;
    
    // Without cast: integer division
    double result1 = numerator / denominator;
    
    // With cast: floating-point division
    double result2 = static_cast<double>(numerator) / denominator;
    
    std::cout << "\nDivision comparison:\n";
    std::cout << "Integer division: " << numerator << " / " << denominator << " = " << result1 << std::endl;
    std::cout << "Float division: " << numerator << " / " << denominator << " = " << result2 << std::endl;
    
    return 0;
}

Output:

Explicit conversion with static_cast:

Double: 3.14159
Explicitly converted to int: 3

ASCII 65 as character: 'A'

Division comparison:
Integer division: 7 / 3 = 2
Float division: 7 / 3 = 2.33333

Common type conversion scenarios

Floating-point to integer conversion

#include <iostream>
#include <cmath>  // For floor, ceil, round

int main()
{
    double values[] = {3.14, 3.99, -2.7, 0.5};
    int numValues = sizeof(values) / sizeof(values[0]);
    
    std::cout << "Floating-point to integer conversions:\n\n";
    
    for (int i = 0; i < numValues; ++i)
    {
        double val = values[i];
        
        std::cout << "Value: " << val << std::endl;
        std::cout << "  static_cast<int>: " << static_cast<int>(val) << " (truncate)\n";
        std::cout << "  floor: " << static_cast<int>(std::floor(val)) << " (round down)\n";
        std::cout << "  ceil: " << static_cast<int>(std::ceil(val)) << " (round up)\n";
        std::cout << "  round: " << static_cast<int>(std::round(val)) << " (nearest)\n\n";
    }
    
    return 0;
}

Output:

Floating-point to integer conversions:

Value: 3.14
  static_cast<int>: 3 (truncate)
  floor: 3 (round down)
  ceil: 4 (round up)
  round: 3 (nearest)

Value: 3.99
  static_cast<int>: 3 (truncate)
  floor: 3 (round down)
  ceil: 4 (round up)
  round: 4 (nearest)

Value: -2.7
  static_cast<int>: -2 (truncate)
  floor: -3 (round down)
  ceil: -2 (round up)
  round: -3 (nearest)

Value: 0.5
  static_cast<int>: 0 (truncate)
  floor: 0 (round down)
  ceil: 1 (round up)
  round: 0 (nearest)

Working with different integer types

#include <iostream>
#include <climits>

int main()
{
    std::cout << "Integer type conversions:\n\n";
    
    // Converting between different integer sizes
    long long veryBigNumber = 1234567890123LL;
    long bigNumber = static_cast<long>(veryBigNumber);
    int normalNumber = static_cast<int>(veryBigNumber);
    short smallNumber = static_cast<short>(veryBigNumber);
    
    std::cout << "Original (long long): " << veryBigNumber << std::endl;
    std::cout << "As long: " << bigNumber << std::endl;
    std::cout << "As int: " << normalNumber << " ";
    if (normalNumber != veryBigNumber)
        std::cout << "(data lost!)";
    std::cout << std::endl;
    
    std::cout << "As short: " << smallNumber << " ";
    if (smallNumber != veryBigNumber)
        std::cout << "(data lost!)";
    std::cout << std::endl;
    
    // Safe range checking
    long longValue = 50000;
    std::cout << "\nSafe conversion checking:\n";
    std::cout << "Long value: " << longValue << std::endl;
    
    if (longValue >= INT_MIN && longValue <= INT_MAX)
    {
        int safeInt = static_cast<int>(longValue);
        std::cout << "Safe conversion to int: " << safeInt << std::endl;
    }
    else
    {
        std::cout << "Cannot safely convert to int - value out of range\n";
    }
    
    return 0;
}

Boolean conversions

#include <iostream>

int main()
{
    std::cout << std::boolalpha;  // Show true/false instead of 1/0
    std::cout << "Boolean conversions:\n\n";
    
    // Numbers to boolean
    std::cout << "Numbers to boolean:\n";
    int values[] = {0, 1, -1, 42, -10};
    int numValues = sizeof(values) / sizeof(values[0]);
    
    for (int i = 0; i < numValues; ++i)
    {
        int val = values[i];
        bool boolVal = static_cast<bool>(val);
        std::cout << "static_cast<bool>(" << val << ") = " << boolVal << std::endl;
    }
    
    // Boolean to numbers
    std::cout << "\nBoolean to numbers:\n";
    bool trueValue = true;
    bool falseValue = false;
    
    std::cout << "static_cast<int>(true) = " << static_cast<int>(trueValue) << std::endl;
    std::cout << "static_cast<int>(false) = " << static_cast<int>(falseValue) << std::endl;
    std::cout << "static_cast<double>(true) = " << static_cast<double>(trueValue) << std::endl;
    
    return 0;
}

Output:

Boolean conversions:

Numbers to boolean:
static_cast<bool>(0) = false
static_cast<bool>(1) = true
static_cast<bool>(-1) = true
static_cast<bool>(42) = true
static_cast<bool>(-10) = true

Boolean to numbers:
static_cast<int>(true) = 1
static_cast<int>(false) = 0
static_cast<double>(true) = 1

Practical applications

Input validation and conversion

#include <iostream>

double celsiusToFahrenheit(double celsius)
{
    return celsius * 9.0 / 5.0 + 32.0;
}

int main()
{
    std::cout << "Temperature Converter\n";
    std::cout << "Enter temperature in Celsius: ";
    
    double celsius;
    std::cin >> celsius;
    
    // Convert to Fahrenheit
    double fahrenheit = celsiusToFahrenheit(celsius);
    
    // Display results with appropriate precision
    std::cout << std::fixed;
    std::cout << celsius << "°C = " << fahrenheit << "°F\n";
    
    // Convert to integer for whole-degree display
    int wholeCelsius = static_cast<int>(std::round(celsius));
    int wholeFahrenheit = static_cast<int>(std::round(fahrenheit));
    
    std::cout << "Rounded: " << wholeCelsius << "°C = " << wholeFahrenheit << "°F\n";
    
    return 0;
}

Grade calculation with type conversions

#include <iostream>

char calculateLetterGrade(double percentage)
{
    // Convert percentage to letter grade
    int rounded = static_cast<int>(std::round(percentage));
    
    if (rounded >= 90) return 'A';
    else if (rounded >= 80) return 'B';
    else if (rounded >= 70) return 'C';
    else if (rounded >= 60) return 'D';
    else return 'F';
}

int main()
{
    std::cout << "Grade Calculator\n\n";
    
    double scores[] = {95.7, 87.3, 73.8, 59.2, 81.5};
    int numScores = sizeof(scores) / sizeof(scores[0]);
    
    double total = 0;
    
    for (int i = 0; i < numScores; ++i)
    {
        double score = scores[i];
        char grade = calculateLetterGrade(score);
        
        std::cout << "Score " << (i + 1) << ": " << score << "% → Grade " << grade << std::endl;
        total += score;
    }
    
    double average = total / numScores;
    char averageGrade = calculateLetterGrade(average);
    
    std::cout << "\nAverage: " << average << "% → Grade " << averageGrade << std::endl;
    
    // Convert to integer for display
    int wholeAverage = static_cast<int>(std::round(average));
    std::cout << "Rounded average: " << wholeAverage << "%\n";
    
    return 0;
}

Output:

Grade Calculator

Score 1: 95.7% → Grade A
Score 2: 87.3% → Grade B
Score 3: 73.8% → Grade C
Score 4: 59.2% → Grade F
Score 5: 81.5% → Grade B

Average: 79.5% → Grade C
Rounded average: 80%

Best practices for type conversion

✅ Use static_cast for explicit conversions

// Good: Explicit and clear
double result = static_cast<double>(numerator) / denominator;
int truncated = static_cast<int>(floatingValue);

// Avoid: C-style casts (less safe)
// double result = (double)numerator / denominator;
// int truncated = (int)floatingValue;

✅ Check ranges when converting to smaller types

#include <iostream>
#include <climits>

bool safeConvertToInt(long value, int& result)
{
    if (value >= INT_MIN && value <= INT_MAX)
    {
        result = static_cast<int>(value);
        return true;
    }
    return false;
}

int main()
{
    long bigValue = 50000;
    int convertedValue;
    
    if (safeConvertToInt(bigValue, convertedValue))
    {
        std::cout << "Safe conversion: " << convertedValue << std::endl;
    }
    else
    {
        std::cout << "Conversion would lose data\n";
    }
    
    return 0;
}

✅ Be explicit about precision loss

// Good: Clear that precision loss is intentional
int wholeNumber = static_cast<int>(3.14159);  // Clearly truncating

// Good: Use appropriate rounding
int rounded = static_cast<int>(std::round(3.14159));  // Clearly rounding

❌ Common mistakes to avoid

// Mistake: Ignoring overflow/underflow
// int smallValue = largeValue;  // May overflow

// Mistake: Unexpected truncation
// double result = 7 / 3;        // Integer division, result is 2.0
double result = 7.0 / 3.0;       // Correct: floating-point division

// Mistake: Dangerous implicit conversions
// unsigned int value = -1;      // Wraps around!

Summary

Type conversion is essential for working with different data types:

Types of conversion:

  • Implicit: Automatic conversion by compiler (safe promotions)
  • Explicit: Manual conversion using static_cast<type>(value)

Common scenarios:

  • Integer ↔ Floating-point conversion
  • Widening conversions (safe): smaller → larger type
  • Narrowing conversions (risky): larger → smaller type
  • Boolean ↔ Numeric conversion
  • Character ↔ Integer conversion

Best practices:

  • Use static_cast for explicit conversions
  • Check ranges when converting to smaller types
  • Be aware of precision loss in narrowing conversions
  • Use appropriate rounding functions when needed
  • Make conversions explicit and intentional

Key rules:

  • static_cast is safer than C-style casts
  • Narrowing conversions may lose data
  • Integer division truncates (use static_cast<double> for precision)
  • Non-zero values convert to true, zero converts to false

Understanding type conversion helps you write more robust code and avoid unexpected data loss or behavior.

Quiz

  1. What's the difference between implicit and explicit type conversion?
  2. What happens when you convert a double to an int?
  3. How do you perform floating-point division with integers?
  4. What's wrong with int result = 7 / 3; if you want the decimal result?
  5. Why is static_cast preferred over C-style casts?

Practice exercises

Try these type conversion exercises:

  1. Write a function that safely converts a double to an int with range checking
  2. Create a program that demonstrates precision loss in various type conversions
  3. Implement a calculator that handles mixed integer and floating-point arithmetic
  4. Write a function that converts between different temperature scales using appropriate type conversions

Continue Learning

Explore other available lessons while this one is being prepared.

View Course

Explore More Courses

Discover other available courses while this lesson is being prepared.

Browse Courses

Lesson Discussion

Share your thoughts and questions

💬

No comments yet. Be the first to share your thoughts!

Sign in to join the discussion