Type conversions, auto, and sizeof
Understand implicit and explicit conversions, narrowing, type deduction with auto, and sizeof.
Learning objectives
- Explain implicit and explicit conversions.
- Recognize integer division and narrowing.
- Use
static_castwhen conversion intent should be visible. - Use
autoandsizeofcorrectly.
Prerequisites: variables, initialization, arithmetic expressions, and the built-in numeric types. Review Variables, values, and data types, Expressions and arithmetic, and Integer ranges and floating-point precision first.
Why types matter in expressions
C++ expressions have types, and those types affect which operations are performed. In particular, dividing two integers performs integer division: the fractional part is discarded.
int a{7};
int b{2};
double wrong = a / b; // 3.0, because integer division happens first
double right{static_cast<double>(a) / b}; // 3.5The cast changes the type used in the division. Converting the final integer result to double cannot restore a fractional part that was already discarded.
Implicit conversions
An implicit conversion happens when the language converts a value without an explicit cast in the source. Some are convenient, such as converting an int to double for a calculation. Others can lose information, such as converting a large integer to a smaller type or a floating-point value to an integer.
Explicit conversions with static_cast
double measurement{9.8};
int whole{static_cast<int>(measurement)}; // whole becomes 9static_cast makes the programmer's intention visible. It does not make every conversion safe: the fractional part is still discarded here. Check the range and meaning before converting.
Type deduction with auto
#include <iostream>
#include <string>
int main() {
auto count{10}; // int
auto price{12.5}; // double
auto title{"C++"}; // const char*
std::string name{"Ada"};
auto name_copy = name; // std::string
std::cout << "count: " << count << '\n';
std::cout << "price: " << price << '\n';
std::cout << "title: " << title << '\n';
std::cout << "name copy: " << name_copy << '\n';
}count: 10 price: 12.5 title: C++ name copy: Ada
C++17 standard note: with a one-element direct-list declaration such as auto count{10};, the corrected rule deduces the element type (here, int); this change is associated with defect report N3922. As originally published, C++11 and C++14 deduced an std::initializer_list for this form, although compiler implementations may apply the defect report retroactively. This course uses C++17 as its baseline. If you need unambiguous deduction across older compilers, auto count = 10; also deduces int.
auto asks the compiler to deduce a type from the initializer. It does not mean that the variable can change type later. Use it when the type is clear from the expression or would be long and repetitive. If you need an owning string, write std::string title{"C++"};.
What sizeof tells you
sizeof reports the size in bytes of an object type or expression. The result type is std::size_t. Exact sizes of many built-in types depend on the implementation, so do not hard-code assumptions such as “int is always 4 bytes.”
Common mistakes
- Converting the result after integer division instead of converting an operand first.
- Assuming
static_castprevents loss of information. - Thinking
autocreates a dynamically typed variable. - Assuming
sizeofmeasures a string's text length; forstd::stringit measures the object representation size, not its character count.
Practice
- Calculate 7 divided by 2 as both integer and floating-point division.
- Use
static_castto calculate an average without integer truncation. - Declare variables with
autofrom an int, double, and std::string initializer; identify their deduced types. - Print
sizeof(int)and explain why the number may differ across systems.
Check your understanding
Why does static_cast<double>(7 / 2) produce 3.0?
Answer: The integer division 7 / 2 is evaluated first and produces 3. The cast then converts 3 to 3.0.
Practice solutions
Show reasoned solutions
7 / 2is3because both operands are integers.7.0 / 2orstatic_cast<double>(7) / 2is3.5.- Convert before division:
static_cast<double>(total) / count. Check thatcountis not zero before dividing. autodeducesintfrom an int initializer,doublefrom a double initializer, andstd::stringfrom thestd::stringvariable in the example. A string literal by itself decays to a pointer in this deduction context.- Print
sizeof(int); it reports the size in bytes on the current implementation. The C++ implementation determines the exact size, subject to the standard's minimum requirements.
Summary
Know the types of operands before an expression is evaluated. Make potentially lossy conversions explicit, use auto for readable type deduction, and treat sizeof results as implementation-dependent measurements.