Coming Soon
This lesson is currently being developed
Introduction to type conversion and static_cast
Learn about converting between different data types.
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
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 tofalse
Understanding type conversion helps you write more robust code and avoid unexpected data loss or behavior.
Quiz
- What's the difference between implicit and explicit type conversion?
- What happens when you convert a double to an int?
- How do you perform floating-point division with integers?
- What's wrong with
int result = 7 / 3;
if you want the decimal result? - Why is
static_cast
preferred over C-style casts?
Practice exercises
Try these type conversion exercises:
- Write a function that safely converts a double to an int with range checking
- Create a program that demonstrates precision loss in various type conversions
- Implement a calculator that handles mixed integer and floating-point arithmetic
- Write a function that converts between different temperature scales using appropriate type conversions
Explore More Courses
Discover other available courses while this lesson is being prepared.
Browse CoursesLesson Discussion
Share your thoughts and questions