C++ PROGRAMMING · 14 MIN STUDY

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_cast when conversion intent should be visible.
  • Use auto and sizeof correctly.

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.5

The 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 9

static_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_cast prevents loss of information.
  • Thinking auto creates a dynamically typed variable.
  • Assuming sizeof measures a string's text length; for std::string it measures the object representation size, not its character count.

Practice

  1. Calculate 7 divided by 2 as both integer and floating-point division.
  2. Use static_cast to calculate an average without integer truncation.
  3. Declare variables with auto from an int, double, and std::string initializer; identify their deduced types.
  4. 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
  1. 7 / 2 is 3 because both operands are integers. 7.0 / 2 or static_cast<double>(7) / 2 is 3.5.
  2. Convert before division: static_cast<double>(total) / count. Check that count is not zero before dividing.
  3. auto deduces int from an int initializer, double from a double initializer, and std::string from the std::string variable in the example. A string literal by itself decays to a pointer in this deduction context.
  4. 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.

References