Source: https://mokxi.com/learn/arduino-data-types
Updated: 2026-10-25

Learn

# Arduino data types: how big each box is

Written by the Mokxi team, updated October 25, 2026

Start building free

Or see every lesson.

- 455 parts on the bench
- 43 boards running now
- 1.00x real time, on every board

Press Run and read the serial monitor

The sketch prints each variable, the size of int and long, and 32000 + 1000 in an int.

Every variable has a type that says what it can hold. On an Arduino Uno, int is 2 bytes and holds -32768 to 32767, long is 4 bytes and holds about plus or minus 2 billion, byte holds 0 to 255, bool holds true or false, char holds one character, and float holds decimals to about seven digits. Pick the type by the biggest number the variable will ever hold.

The circuit above is the code bench, an Uno with three lamps. Press Run and the serial monitor prints each variable the sketch made, then "sizeof(int) = 2" and "sizeof(long) = 4", and last "32000 + 1000 in an int = -32536": an int that went over the top and came around the bottom.

Below is the size of each type on an Uno and an ESP32, the four ways numbers go wrong without an error, and how to turn a float into an int, each run in Mokxi with what it printed.

Want the step-by-step version? The lesson "Variables have a size" walks through this with checkpoints.
Open the lesson

## The types, and their sizes

Here are the five variables in the sketch running above, one of each common type. A variable is made by writing its type, a name and, usually, a starting value. char grade = 'A'; uses single quotes, because a char is one character.

The sizes are not the same on every board. We printed sizeof for each type on an Uno and on an ESP32-C3. bool, char and byte were 1 byte on both, and long and float 4 on both. But int was 2 bytes on the Uno and 4 on the ESP32-C3, and double was 4 on the Uno and 8 on the ESP32-C3. A sketch that counts past 32767 in an int works on an ESP32 and goes wrong on an Uno. When the size matters, say it: int16_t, int32_t and uint8_t are the same size everywhere.

firmware/uno/examples/cppvars (the variables running above)

## When a number does not fit

Nothing stops a number at the top of its type. It wraps around to the bottom, as the sketch above showed with 32000 + 1000 printing -32536. int x = 40000; printed -25536, and the build tab warned: implicit conversion from 'long' to 'int' changes value from 40000 to -25536.

Unsigned types wrap the other way. unsigned int u = 0; minus one printed 65535, and a byte at 255 plus one printed 0. That is why a counter in a byte makes a loop that never ends, and why times from millis() belong in an unsigned long, which lasts 49.7 days before it wraps.

## The sum that overflows before it is stored

This one catches people who did pick the right type. long minute = 60 * 1000; printed -5536, even though a long holds 60000 easily. The sum is worked out first, in int because both numbers are ints, and it overflows there; only the wrong answer is put in the long. Clang warned: overflow in expression; result is -5'536 with type 'int'.

Make one of the numbers a long and the whole sum is done in long. 60 * 1000L printed 60000, and 60UL * 60 * 1000 for an hour printed 3600000. Any time a sum of times or sizes could pass 32767, put L or UL on its first number.

Too big before it lands

## Whole numbers divide into whole numbers

Divide one int by another and the answer is an int, with the remainder thrown away. 5 / 2 printed 2, and 5 / 2.0 printed 2.50, because one decimal in the sum makes the whole sum decimal. Putting the answer in a float is too late: float half = 5 / 2; printed 2.00, and the average of 3 and 4 came out as 3.00 until it was divided by 2.0.

The version of this everyone writes once is turning a reading into volts. With 3.3 V on A0, analogRead(A0) * (5 / 1023) printed 0.00, because 5 / 1023 is 0 in whole numbers. analogRead(A0) * (5.0 / 1023.0) printed 3.30.

Dividing

## float: about seven digits, and never quite exact

A float keeps about seven significant digits and rounds the rest. float big = 123456789; printed 123456792.00, with a warning that the value changed. Decimals are stored in binary, so most of them are slightly off: adding 0.1 ten times printed 1.0000001, and sum == 1.0 was false. Compare floats with a margin, as in abs(sum - 1.0) < 0.001, never with ==.

On an Uno, double is the same 4-byte float, so it does not buy any more digits. One third printed to nine places was 0.333333349 as a double on the Uno and 0.333333333 on the ESP32-C3, where double is 8 bytes.

## float to int, and char against byte

Putting a float into an int cuts off the decimals; it does not round. float f = 3.99; stored in an int printed 3, and (int)-3.7 printed -3: toward zero, both ways. To round to the nearest whole number, use round(): round(3.5) printed 4 and round(2.5) printed 3, halves going away from zero. For a positive number, (int)(f + 0.5) does the same and printed 4.

char and byte are both one byte, but they print differently. char c = 65; printed A, because a char is printed as the letter with that code, and byte n = 65; printed 65. A bool prints as 1 or 0.

Cutting and rounding

## Questions

What is the difference between int and long in Arduino?

On an Uno an int is 2 bytes, -32768 to 32767, and a long is 4 bytes, about plus or minus 2.1 billion. On an ESP32 both are 4 bytes. Use long, or unsigned long for millis(), for anything that can pass 32767.

How do I convert a float to an int in Arduino?

Assign it, or write (int)f, and the decimals are cut off: 3.99 becomes 3. Use round(f) to round to the nearest whole number instead.

Why does my Arduino math give a negative number?

The answer went past the top of its type and wrapped round. On an Uno, 32000 + 1000 in an int is -32536, and 60 * 1000 is -5536 even when stored in a long, because the sum is worked out in int. Use long and write 60 * 1000L.

Is double more precise than float on Arduino?

Not on an Uno, Nano or Mega, where double is the same 4-byte float. On an ESP32, a Raspberry Pi Pico or an Uno R4, double is 8 bytes and keeps about 15 digits.

What is the difference between byte and char?

Both are one byte. A byte holds 0 to 255 and prints as a number; a char is meant for a character and prints as a letter, so 65 prints as A.

Related

## Keep going

Arduino const vs #define: Which One to Use Arduino millis() Overflow: Why Subtraction Works Arduino map() Function: Scale Any Reading Arduino Array: Lists of Pins, Patterns and Notes Arduino "Low Memory Available" and "Sketch Too Big" Arduino Bitwise Operators and bitRead, Explained Arduino Struct: Group Values, With Examples Arduino String: Join, Compare, Convert, Split Arduino Static Variable vs Global, With Examples The free Arduino simulator The Arduino Uno simulator

Sources

## Where the facts on this page come from

- Arduino reference: int
- Arduino reference: float
- Arduino reference: double

## Build this for real

Open the editor, change a value and watch the number move with it. Nothing to install, and no account needed.

Start building free Open the editor
