CalculateeLearning paths
C/C++8–10 min read

C/C++ Types, Units and Integer Arithmetic

Choose numeric types carefully and avoid overflow, truncation and unit-conversion mistakes.

Mental model

A variable is a container with a declared size and interpretation. Changing its label does not automatically give it more room or fractional precision.

8b8b8b8b8b8b8b8buint32_t = 4 bytesuint16_twidth controls range and layout
A type determines storage width and interpretation; fixed-width types make hardware code more portable.
UNDERSTAND THE BEHAVIOR
01

A type determines the values an object can represent and the operations performed on it. An int is not guaranteed to have the same width on every microcontroller. Fixed-width types such as uint16_t are useful when available and when an exact width is part of a protocol or hardware interface. Keep physical units in variable names to prevent mixing milliseconds with seconds.

02

Integer division discards the fractional part toward zero. Assigning 5/2 to a float still gives 2.0 because the division happened before the assignment. Use a floating operand, such as 5.0f/2.0f, when fractional arithmetic is intended. For integer scaling, multiply in a sufficiently wide type before dividing, and decide whether truncation or rounding is appropriate.

03

Overflow can happen in an intermediate expression even when the final variable is wide. On a platform with a 16-bit int, multiplying two promoted small integers may overflow before assignment to a 32-bit result. Convert an operand to a sufficiently wide unsigned type before multiplication and verify that the maximum product fits.

04

C and C++ are separate languages with overlapping syntax. C++ adds stronger abstractions such as classes and standard containers; code valid in one language is not automatically valid in the other. The example below is C++17. It uses a 32-bit intermediate for a millivolt estimate and makes its endpoint-based ADC scaling convention explicit.

Why it matters

Choose numeric types carefully and avoid overflow, truncation and unit-conversion mistakes.

Core ideas

  • The type of the expression matters before assignment.
  • Document units and numeric ranges.
  • Do not assume int is always 32 bits.
Key equationsInteger 5 / 2 = 2Endpoint estimate: mV = code × Vref_mV / maximum_code
EXAMPLE

Work through a practical example

1Assume a 10-bit ADC code of 512 and a 3300 mV reference.

2Use a 32-bit multiplication: 512 × 3300 = 1,689,600.

3Divide by 1023 using this endpoint-estimate convention: result is 1651 mV after truncation.

4Actual quantizer step size is Vref/1024; transfer-function conventions and reference accuracy must be checked separately.

Common mistake

Casting only the final result after overflow or integer division has already occurred.

Code example

C++17 — standalone program; expected output: 1651 mV

#include <cstdint>
#include <cstdio>
int main() {
  const std::uint16_t code = 512;
  const std::uint32_t mv =
      static_cast<std::uint32_t>(code) * 3300u / 1023u;
  std::printf("%lu mV\n", static_cast<unsigned long>(mv));
}

Read and run this example in the stated environment. Code is displayed here; it does not execute in your browser.

RememberThe type of the expression matters before assignment.

Practice and check your understanding

Try each question before opening the worked answer.

1. What does float x = 3 / 2 store?

Show answer and reasoning

1.0. Both operands are integers, so the division yields 1 before conversion to float.

2. Why widen an operand before multiplying?

Show answer and reasoning

To make the multiplication occur in the wider type, provided that type can represent the product. Widening only after multiplication cannot repair overflow.

Continue learning

Technical references and further reading

References are for further study, not endorsements. Report an error or suggest an improvement.

Progress stays on this browser only. Clearing site data removes it; it does not sync across devices.