本文へ移動
同じ「箱」でも、
中に入れられる中身は違う。
Arduinoのデータ型を意識せずになんとなく書いていると、「小数点が消える」「文字列がエラーになる」「センサー値が思った通りに表示されない」といったつまずきに必ず出会います。この記事では、変数を「ラベル付きの箱」にたとえながら、int・float・char・String・bool・byte・longという主要なデータ型の違いと使い分けを、豊富な具体例で専門用語ゼロから徹底的に解説します。

変数とは何か(箱のたとえで理解する)
変数とは、一言でいうと「名前の付いた箱」です。箱の中に数字や文字を入れておき、その名前を呼べば、いつでも中身を取り出したり書き換えたりできます。
int sensorValue = 512;
// int → 箱に入れられる中身の種類(データ型)
// sensorValue → 箱の名前(変数名)
// 512 → 今、箱に入っている中身(値)
ただし、この「箱」には1つ重要な決まりがあります。それは「1つの箱には、決めた種類の中身しか入れられない」ということです。たとえば、整数専用の箱に「こんにちは」という文字を入れようとしたり、文字専用の箱に小数を入れようとしたりすると、エラーになったり、意図しない結果になったりします。つまり、この「箱の種類」にあたるのが、この記事のテーマであるデータ型です。
変数の基本的な使い方はArduinoのコードの書き方(コピペ可20選)でも扱っていますが、この記事ではデータ型そのものに焦点を絞って、さらに詳しく掘り下げます。正式な定義はArduino公式のUsing Variables in Sketches ↗で確認できます。
データ型とは何か・なぜ使い分けるのか
データ型とは「その箱に、どんな種類の中身を、どれくらいの大きさまで入れられるか」を決めるルールです。Arduinoのようなマイコン(小さなコンピューター)は、パソコンと違ってメモリ(記憶できる容量)がとても少ないという特徴があります。そのため、型を正しく選ぶことがとても重要になります。
| 型 | 入る中身 | 使用メモリ |
|---|---|---|
bool |
true / falseの2択 | 1バイト |
byte |
0〜255の整数 | 1バイト |
int |
-32,768〜32,767の整数 | 2バイト |
long |
約-21億〜21億の整数 | 4バイト |
float |
小数を含む数(約7桁の精度) | 4バイト |
char |
1文字だけ | 1バイト |
String |
複数文字の文字列 | 文字数に応じて変動 |
たとえば「boolで十分なところにfloatを使う」ようなことをすると、必要以上にメモリを消費してしまいます。なぜなら、Arduino Uno / Nanoが持つSRAM(変数を保存するメモリ)はわずか2KB(2,048バイト)しかないからです。このように、この「使い分け」が実際に動作の安定性に直結します。詳しくはArduino公式のメモリ削減ガイド ↗でも解説されています。
int型|整数を扱う(範囲とオーバーフロー)
intは「integer(整数)」の略で、Arduinoで最もよく使われる型です。小数点のない整数を、-32,768〜32,767の範囲で扱えます。
例1:ピン番号やセンサー値をintで扱う
int ledPin = 8; // ピン番号
int sensorValue = 0; // センサーの読み取り値
void loop() {
sensorValue = analogRead(A0); // 0〜1023なのでintで十分
}
たとえば、ピン番号(0〜13程度)も、analogRead()の結果(0〜1023)も、余裕をもってintの範囲に収まります。analogRead・analogWriteそのものの使い方はanalogRead・analogWriteの使い方で詳しく解説しています。したがって、特別な理由がない限り、整数はまずintを検討するのが基本方針です。
例2:範囲を超えるとどうなるか(オーバーフロー)
int count = 32767; // intの最大値
count = count + 1; // 1を足すとどうなる?
Serial.println(count); // 32768ではなく、-32768と表示される
intの最大値32,767を超える計算をすると、値は最小値の-32,768へと「一周」してしまいます。これをオーバーフローと呼びます。カウンターの数字が大きくなりすぎる可能性がある処理では、この範囲を意識しておく必要があります。より大きな整数を扱いたい場合は、6章で紹介するlong型を検討してください。
より詳しい仕様は、Arduino公式のint言語リファレンス ↗にまとまっています。
float型|小数を扱う(精度の落とし穴)
floatは小数点を含む数を扱う型です。電圧の計算(例:2.73V)や、平均値の計算など、整数だけでは表現できない値を扱う時に使います。たとえば、温湿度センサーが返す「24.6℃」のような値も、まさにfloatの出番です。実際の配線・コード例はArduinoで温湿度センサーを使う方法|DHT11・DHT22の使い分けで確認できます。
例3:センサー値を電圧に変換する(float の出番)
int rawValue = analogRead(A0); // 0〜1023(整数でよい)
float voltage = rawValue * (5.0 / 1023.0); // 電圧は小数になるのでfloat
Serial.println(voltage); // 例:2.73
例4:int同士の割り算で小数点が消える罠
int a = 5;
int b = 2;
float result = a / b; // 2.5になってほしいが…
Serial.println(result); // 実際には 2.00 と表示される
なぜなら、右辺のa / bは両方ともint型なので、計算そのものが「整数の割り算」として行われ、小数点以下は計算される前に切り捨てられてしまうからです。その結果である「2」を、後からfloat型のresultに入れているだけなので、2.00にしかなりません。そのため、計算式の中に、最低1つは小数を含めておく必要があります。
FIX ↓
float result = a / (float)b; // bをfloatに変換してから割り算する
// または
float result = (float)a / b; // aをfloatに変換してから割り算する
Serial.println(result); // 2.50 と表示される
(float)bのように型の名前をかっこで囲んで数値の前に置くと、「この値をfloat型として扱ってください」という指示になります。これをキャスト(型変換)と呼びます。float型そのものの定義は、Arduino公式のfloat言語リファレンス ↗を参照してください。
floatはintに比べて計算に時間がかかり、メモリも多く消費します。そのため、「小数点が本当に必要か」を考え、不要ならintのままにしておく方が、多くの場面で無難です。
文字列を扱う|char配列とString型の違い
Arduinoで文字や文章(文字列)を扱う方法は、実は1つではありません。大きく分けてchar配列(C言語スタイルの文字列)とString型(オブジェクトとしての文字列)の2種類があり、それぞれ得意・不得意が異なります。
stringという型は存在しません。文字列を扱うための正式な型は、頭文字が大文字のStringです。この記事のタイトルにある「string」は一般的な呼び方として使っていますが、実際にコードを書く時は必ず大文字のStringと書いてください。例5:char(1文字だけ)とchar配列(複数文字)
char grade = 'A'; // シングルクォートで1文字だけ
char message[] = "Hello Arduino"; // ダブルクォートで複数文字(char配列)
Serial.println(grade); // A
Serial.println(message); // Hello Arduino
charは本来「1文字だけ」を入れる箱です。しかし、char message[]のように[]を付けて宣言すると、文字を並べて入れられる「箱の集合(配列)」になり、結果として文章を保存できます。つまり、これがC言語スタイルの文字列で、「文字列は文字の配列である」という考え方に基づいています。配列そのものの基本的な使い方はArduinoの配列の使い方|複数センサーの値を一元管理するでも扱っているので、あわせて読むと理解が深まります。
例6:String型で文字列を扱う(初心者に扱いやすい方法)
String message = "Hello Arduino"; // String型(大文字のS)
String name = "Arduino";
String greeting = "Hello, " + name + "!"; // +でつなげられる(結合)
Serial.println(greeting); // Hello, Arduino!
String型は+で文字列同士をつなげたり、.length()で文字数を調べたり、.indexOf()で特定の文字を探したりと、便利な機能(メソッド)がたくさん用意されています。そのため、char配列を直接操作するより、初心者には扱いやすく感じられるはずです。
比較:char配列とStringはどう選ぶか
char配列(C言語スタイル)
- メモリの使用量が少なく、安定している
- +での結合など、直感的な操作がしにくい
- 長時間動かし続けるプログラム向き
- メモリが少ないボードでも安心
String型(オブジェクト)
- +で結合でき、直感的で書きやすい
- 便利なメソッドが豊富
- 使い続けるとメモリの断片化を起こしやすい
- まず学ぶならこちらがおすすめ
String型は、文字列の長さが変わるたびに内部でメモリの確保・解放を繰り返します。そのため、これを長時間繰り返すと、メモリが虫食い状態になる「断片化」という現象が起き、あるとき突然動かなくなることがあります。ただし、表示用のメッセージなど短期的な用途では問題になりにくいので、24時間動かし続けるようなシステムでのみ、char配列への置き換えを検討してください。
char・Stringそれぞれの正式な定義は、Arduino公式のchar言語リファレンス ↗とString()言語リファレンス ↗に掲載されています。
その他のよく使う型|bool・byte・long・unsigned long
int・float・String以外にも、Arduinoでは目的に応じたいくつかの型がよく使われます。それぞれ具体例で見ていきましょう。
例7:bool(はい/いいえの2択)
bool isPressed = false;
isPressed = digitalRead(2) == LOW;
if (isPressed) {
Serial.println("ボタンが押されています");
}
trueかfalseの2択しか入らない、最小サイズの型です。そのため、ボタンの状態や、条件の結果を保存しておく変数によく使われます。boolを使ったif文の書き方はArduinoのif文の書き方完全ガイド|ボタン・センサーで条件分岐をマスターする書き方で詳しく解説しています。
例8:byte(0〜255の小さな整数)
byte brightness = 128; // analogWriteに渡す値(0〜255)は
analogWrite(9, brightness); // byte型で十分収まる
0〜255の範囲しか使わないと分かっている値には、intよりもメモリの少ないbyteが向いています。たとえば、analogWrite()に渡す明るさの値などが代表例です。
例9:long と unsigned long(大きな整数・時間の記録)
long totalSteps = 1500000; // intでは収まらない大きな数
unsigned long startTime; // millis()の戻り値専用
void setup() {
startTime = millis(); // 起動からの経過時間(ミリ秒)
}
longはintの4倍のメモリ(4バイト)を使う代わりに、約-21億〜21億という非常に大きな整数を扱えます。unsigned longはマイナスの値を扱わない代わりに、0〜約42億という、さらに広い範囲の正の整数を扱えます。millis()(起動してからの経過時間)の戻り値は、このunsigned longで受け取るのが決まりです。millis()を使ってdelay()に頼らずに時間管理する書き方はArduinoのmillis()でdelayを使わない書き方で詳しく解説しています。
| 型 | 範囲 | よくある用途 |
|---|---|---|
| bool | true / false | ボタンの状態、条件の結果 |
| byte | 0 〜 255 | analogWriteの値、RGBの色の要素 |
| int | -32,768 〜 32,767 | ピン番号、analogReadの結果 |
| long | 約 -21億 〜 21億 | 大きなカウンター、計算結果 |
| unsigned long | 0 〜 約42億 | millis()・micros()の戻り値 |
bool・byte・long・unsigned longの各仕様は、Arduino公式のbool・byte・long・unsigned long ↗の各言語リファレンスでまとめて確認できます。
型を混ぜて計算する時の注意点
異なる型同士を計算に混ぜると、Arduinoは自動的にどちらかの型に合わせて計算します(これを暗黙の型変換と呼びます)。便利な反面、意図しない結果につながることもあるので、代表的なパターンを押さえておきましょう。
例10:int × float の計算
int count = 3;
float price = 1.5;
float total = count * price; // int × float → floatとして計算される
Serial.println(total); // 4.50
つまり、片方でもfloatが混ざっていれば、計算全体がfloatとして行われます。これは4章で見た「int同士だけは危険」という話の裏返しでもあります。
例11:byteの範囲を超えるとどうなるか
byte value = 250;
value = value + 10; // 260になってほしいが…
Serial.println(value); // 実際には 4 になる(260 - 256)
byteは0〜255の256段階しかないため、intよりもずっと簡単に上限を超えてしまいます。したがって、「この値は本当にその型の範囲に収まるか」を常に意識してください。
例12:StringとintをつなげるにはString()で変換する
int sensorValue = 512;
String message = "センサー値: " + String(sensorValue); // intをStringに変換してから結合
Serial.println(message); // センサー値: 512
文字列と数字は、そのままでは結合できません。そこで、String(数字)のように書くことで、数字を文字列に変換してから結合できます。
ここまで見てきたint同士の割り算やbyteのオーバーフローは、多くの場合コンパイル時にはエラーにならず、「動くけれど結果がおかしい」という形で表れます。逆に、まったく互換性のない型を代入しようとした場合はコンパイルエラーになります。エラーメッセージの読み方に不安がある場合はArduinoのコンパイルエラー一覧|書き込み・動作トラブル対処法を参考にしてください。
実践コード:型を組み合わせたセンサーログ
最後に、ここまで学んだ型を1つのコードにまとめた実践例です。ここでは、bool・int・float・Stringを、それぞれの得意分野で使い分けています。
const int SENSOR_PIN = A0;
const int BUTTON_PIN = 2;
const int THRESHOLD = 700;
void setup() {
pinMode(BUTTON_PIN, INPUT_PULLUP);
Serial.begin(9600);
}
void loop() {
int rawValue = analogRead(SENSOR_PIN); // int:整数の生データ
float voltage = rawValue * (5.0 / 1023.0); // float:電圧に変換
bool isAlert = rawValue >= THRESHOLD; // bool:しきい値判定の結果
bool buttonPressed = digitalRead(BUTTON_PIN) == LOW; // bool:ボタンの状態
String status = isAlert ? "警告" : "正常"; // String:人が読むための状態表示
Serial.print("値: ");
Serial.print(rawValue);
Serial.print(" / 電圧: ");
Serial.print(voltage);
Serial.print("V / 状態: ");
Serial.print(status);
if (buttonPressed) {
Serial.print(" / ボタン押下あり");
}
Serial.println();
delay(200);
}
コードのポイントを分解して読む
あわせて確認しておきたいこと
出力結果をシリアルモニタで見やすく確認するコツはArduinoのシリアルモニタ活用術|デバッグを爆速にするコツを、センサーごとの特性や配線はブレッドボード完全攻略ガイドや圧センサーを用いた電子工作の基礎編で解説しています。
型の選び方チェックリスト
「この値、どの型にすればいいんだろう?」と迷った時は、まず上から順番にこのチェックリストを確認してみてください。
true / falseの2択か?→ boolを使う。
0〜255に収まる整数か?→ byteを検討する(analogWriteの値など)。
小数点は本当に必要か?→ 不要ならint、必要ならfloat。
-32,768〜32,767に収まる整数か?→ 収まるならint、収まらないならlong。
millis()やmicros()の結果を受け取るか?→ 必ずunsigned longを使う。
1文字だけか、複数文字の文章か?→ 1文字ならchar、文章ならString(またはchar配列)。
長時間動かし続けるプログラムか?→ 文字列を多用するならchar配列も検討する。
「必要な範囲に収まる、いちばん小さい型を選ぶ」——これがメモリの少ないArduinoにおける型選びの大原則です。ただし、動かしてみて実際にメモリ不足の警告が出ない限りは、最初からbyteやlongまで神経質に使い分ける必要はありません。つまり、まずはint・float・Stringの3つを正しく使い分けられれば、多くのコードは十分に書けます。
FAQ・まとめ
intとfloat、迷ったらどちらを使えばいいですか?
扱う値に小数点が必要ないなら、迷わずintを使ってください。intの方が処理が速く、メモリの消費も少なく、Arduinoが最も得意とする型だからです。電圧や平均値のように小数点以下の情報が本当に必要な時だけ、floatを使うのが基本方針です。
文字列を扱うときは、char配列とString型のどちらを使うべきですか?
メモリに余裕があり、初心者のうちはString型の方が直感的で書きやすいためおすすめです。ただし、String型は使い続けるとメモリの断片化という問題を起こしやすいため、長時間動かし続けるプログラムや、メモリの少ないボードでは、char配列(C言語スタイルの文字列)を使う方が安全です。
stringとStringは同じものですか?
いいえ、別物です。小文字のstringはArduinoの言語には存在しない名前で、そのまま使うとエラーになります。大文字で始まるStringが、Arduinoで文字列を扱うためのクラス(型のようなもの)の正式な名前です。大文字と小文字を間違えないようにしてください。
int同士で割り算をすると、なぜ小数点が消えるのですか?
int型は整数だけを扱う型で、小数点以下を保存する場所がないためです。5 / 2のようにint同士で割り算をすると、結果は2.5ではなく2になり、小数点以下は切り捨てられます。小数点以下の結果が必要な場合は、どちらか一方の数値に小数点を付ける(5.0 / 2のように書く)ことで、計算全体がfloatとして扱われるようになります。
型を間違えるとコンパイルエラーになりますか?
型によります。intの箱にStringを代入しようとするなど明らかに互換性のない代入はコンパイルエラーになりますが、int同士の割り算で小数点が消える、byteの範囲を超えて値が一周するといった問題の多くは、エラーにはならず「動くけれど結果がおかしい」という形で表れます。エラーにならない分、逆に見つけにくいバグの原因になりやすいので注意してください。
変数とデータ型は、Arduinoのコードを読み書きするための土台です。「箱には決まった種類の中身しか入らない」「型によって使えるメモリと範囲が違う」という2つの考え方さえ押さえれば、int同士の割り算で小数点が消える不思議も、stringと書いてエラーになる理由も、すべて自然に理解できるようになります。まずは8章の実践コードを実際に書き換えて、それぞれの型がどんな場面で活躍するのかを、その目で確かめてみてください。
コメント