C++で見かける%dは、主にprintfやscanfなどのC言語由来の入出力関数で使われる書式指定子です。
たとえば、次のように使います。
#include <cstdio>
int main() {
int x = 10;
std::printf("%d\n", x);
}
出力は次のようになります。
10
この場合、%dは「ここに整数を10進数で表示する」という意味を持ちます。
ただし、%dはC++の文法そのものではありません。
"%d"は文字列の一部であり、それをprintfやscanfなどの関数が特別な意味として解釈しています。
そのため、std::coutでは%dは特別な意味を持ちません。
#include <iostream>
int main() {
std::cout << "%d";
}
出力は次のようになります。
%d
std::coutは%dを整数用の指定子として扱わず、単なる文字列として表示します。
%dの基本的な意味
%dは10進整数を表す指定子
%dは、10進数の符号付き整数を扱うための書式指定子です。
printfでは、int型の値を10進数で表示するために使います。
#include <cstdio>
int main() {
int age = 20;
std::printf("年齢は%d歳です\n", age);
}
出力は次のようになります。
年齢は20歳です
%dのdは、decimal、つまり「10進数」を意味すると考えると覚えやすいです。
printfではint型の値を渡す
printfで%dを使う場合、基本的には対応する引数としてint型の値を渡します。
int x = 123;
std::printf("%d\n", x);
出力は次のようになります。
123
負の数も表示できます。
int x = -45;
std::printf("%d\n", x);
出力は次のようになります。
-45
つまり、printfにおける%dは「int型の値を10進数で表示する指定子」と考えるとよいです。
printfでの%dの使い方
基本的な使い方
printfでは、文字列の中に%dを書き、その後ろに表示したい整数値を渡します。
#include <cstdio>
int main() {
int x = 100;
std::printf("xの値は%dです\n", x);
}
出力は次のようになります。
xの値は100です
%dの位置に、後ろで指定したxの値が入ります。
複数の%dを使う場合
%dを複数使うこともできます。
#include <cstdio>
int main() {
int a = 10;
int b = 20;
std::printf("aは%d、bは%dです\n", a, b);
}
出力は次のようになります。
aは10、bは20です
この場合、1つ目の%dにa、2つ目の%dにbが対応します。
重要なのは、%dの数と、後ろに渡す値の数を一致させることです。
次のようなコードは間違いです。
std::printf("%d %d\n", 10);
%dが2つあるのに、引数が1つしかありません。このようなコードは未定義動作になります。
未定義動作とは、プログラムの動作がC++の規格上保証されない状態のことです。
変な値が表示されるだけでなく、環境によってはクラッシュする可能性もあります。
正しくは次のように書きます。
std::printf("%d %d\n", 10, 20);
scanfでの%dの使い方
scanfでは整数を入力するために使う
scanfでも%dを使います。
scanfの場合、%dは「入力された10進整数を読み取る」という意味になります。
#include <cstdio>
int main() {
int x;
std::printf("整数を入力してください: ");
std::scanf("%d", &x);
std::printf("入力された値は%dです\n", x);
}
たとえば、ユーザーが次のように入力したとします。
25
出力は次のようになります。
入力された値は25です
scanfでは&が必要
scanfでint型の変数に値を入力する場合は、変数名の前に&を付けます。
int x;
std::scanf("%d", &x);
これは、scanfが変数に値を書き込むために、変数そのものではなく変数のアドレスを必要とするからです。
xは変数の値を表します。
x
一方、&xは変数xが置かれている場所、つまりアドレスを表します。
&x
scanf("%d", &x)では、入力された整数をxの場所に保存します。
次のように&を付け忘れると間違いです。
int x;
std::scanf("%d", x); // 間違い
%dに対応するscanfの引数は、intではなくint*、つまりint型変数のアドレスである必要があります。
scanfの戻り値も確認すると安全
実用的なコードでは、scanfの戻り値を確認すると安全です。
#include <cstdio>
int main() {
int x;
if (std::scanf("%d", &x) == 1) {
std::printf("入力された値は%dです\n", x);
} else {
std::printf("整数が正しく入力されませんでした\n");
}
}
scanfは、読み取りに成功した項目数を返します。
%dが1つだけの場合、整数の読み取りに成功すれば1を返します。
整数として読み取れない入力が来た場合は、失敗として扱えます。
printfとscanfでの%dの違い
printfでは値を渡す
printfでは、表示したい値そのものを渡します。
int x = 10;
std::printf("%d\n", x);
この場合、xの値である10が表示されます。
scanfではアドレスを渡す
一方、scanfでは、入力された値を保存する場所が必要です。
そのため、変数のアドレスを渡します。
int x;
std::scanf("%d", &x);
この違いは非常に重要です。
まとめると、次のようになります。
std::printf("%d", x); // xの値を表示する
std::scanf("%d", &x); // 入力された値をxに保存する
初心者が混乱しやすいポイントなので、printfではx、scanfでは&xと覚えておくとよいです。
%dと型の関係
%dは基本的にint型用
%dは基本的にint型の値に対応します。
int x = 100;
std::printf("%d\n", x);
これは正しい使い方です。
一方で、型が異なる値に%dを使うと問題が起きることがあります。
たとえば、long long型の値に%dを使うのは間違いです。
long long x = 10000000000LL;
std::printf("%d\n", x); // 間違い
%dはintを期待しますが、実際にはlong longを渡しているため、未定義動作になります。
正しくは%lldを使います。
long long x = 10000000000LL;
std::printf("%lld\n", x);
charやshortは整数昇格される
charやshortをprintfに渡すと、多くの場合intに昇格して渡されます。
たとえば、次のコードは一般的に問題ありません。
short s = 10;
std::printf("%d\n", s);
shortはprintfに渡されるときにintへ変換されるため、%dで表示できます。
charも同様です。
char c = 'A';
std::printf("%d\n", c);
ASCII互換環境では、多くの場合次のように表示されます。
65
ただし、'A'が必ず65であるとC++規格上決まっているわけではありません。
現在の一般的な環境ではASCII互換であることが多いため、実際には65になることが多いです。
文字として表示したい場合は、%dではなく%cを使います。
char c = 'A';
std::printf("%c\n", c);
出力は次のようになります。
A
boolを%dで表示すると0または1になる
bool型の値を%dで表示すると、trueは1、falseは0として表示されます。
bool flag = true;
std::printf("%d\n", flag);
出力は次のようになります。
1
bool flag = false;
std::printf("%d\n", flag);
出力は次のようになります。
0
これは、boolがprintfに渡されるときにintへ昇格されるためです。
ただし、C++らしく表示するなら、std::coutとstd::boolalphaを使う方法もあります。
#include <iostream>
int main() {
bool flag = true;
std::cout << std::boolalpha << flag << '\n';
}
出力は次のようになります。
true
整数型ごとの書式指定子
よく使う整数用の書式指定子
%d以外にも、整数型にはさまざまな書式指定子があります。
| 書式指定子 | 対応する型 | 意味 |
|---|---|---|
%d | int | 符号付き10進整数 |
%i | int | 整数 |
%u | unsigned int | 符号なし10進整数 |
%ld | long | long型の符号付き10進整数 |
%lu | unsigned long | unsigned long型の符号なし10進整数 |
%lld | long long | long long型の符号付き10進整数 |
%llu | unsigned long long | unsigned long long型の符号なし10進整数 |
%x | unsigned int | 16進数、小文字 |
%X | unsigned int | 16進数、大文字 |
%o | unsigned int | 8進数 |
%zu | std::size_t | size_t型の符号なし整数 |
たとえば、次のように使います。
#include <cstdio>
#include <cstddef>
int main() {
int a = 10;
long b = 20;
long long c = 30;
unsigned int d = 255;
std::size_t e = 40;
std::printf("%d\n", a);
std::printf("%ld\n", b);
std::printf("%lld\n", c);
std::printf("%u\n", d);
std::printf("%zu\n", e);
}
size_tには%zuを使う
C++では、sizeofやstd::string::size()の戻り値としてstd::size_tがよく使われます。
std::size_tをprintfで表示する場合、%dではなく%zuを使います。
#include <cstdio>
#include <string>
int main() {
std::string s = "hello";
std::printf("%zu\n", s.size());
std::printf("%zu\n", sizeof(int));
}
size_tはintとは異なる型なので、%dで表示するのは適切ではありません。
%dと%iの違い
printfではほぼ同じ
printfで使う場合、%dと%iはどちらも符号付き10進整数を表示します。
int x = 10;
std::printf("%d\n", x);
std::printf("%i\n", x);
どちらも次のように表示されます。
10
10
printfで使う場合は、ほとんど同じものとして考えて問題ありません。
scanfでは意味が異なる
一方、scanfでは%dと%iに違いがあります。
%dは、入力を10進数として読み取ります。
int x;
std::scanf("%d", &x);
たとえば、010と入力すると、10進数の10として扱われます。
一方、%iは入力の形式によって、10進数・8進数・16進数を自動判別します。
int x;
std::scanf("%i", &x);
たとえば、次の入力は10進数として扱われます。
10
値は10です。
次の入力は、先頭に0があるため8進数として扱われます。
010
この場合、値は10進数で8です。
次の入力は、先頭に0xがあるため16進数として扱われます。
0x10
この場合、値は10進数で16です。
初心者のうちは、10進整数を入力したいなら%dを使うほうがわかりやすいです。
%dで表示幅を指定する方法
桁幅を指定する
%dでは、表示するときの幅を指定できます。
std::printf("|%5d|\n", 123);
出力は次のようになります。
| 123|
%5dは、全体を5文字幅で表示するという意味です。
123は3文字なので、左側にスペースが2つ入ります。
0埋めする
数字の前を0で埋めたい場合は、%05dのように書きます。
std::printf("%05d\n", 123);
出力は次のようになります。
00123
これは、全体を5文字幅にし、足りない部分を0で埋める指定です。
日付や時刻の表示でもよく使われます。
int month = 7;
int day = 5;
std::printf("%02d/%02d\n", month, day);
出力は次のようになります。
07/05
左寄せする
幅を指定した場合、通常は右寄せになります。
std::printf("|%5d|\n", 123);
出力は次のようになります。
| 123|
左寄せしたい場合は、-を使います。
std::printf("|%-5d|\n", 123);
出力は次のようになります。
|123 |
符号を常に表示する
正の数にも+を表示したい場合は、%+dを使います。
std::printf("%+d\n", 10);
std::printf("%+d\n", -10);
出力は次のようになります。
+10
-10
%dを文字として表示したい場合
%そのものを表示するには%%を使う
printfでは、%は書式指定子の始まりとして扱われます。
そのため、%dという文字そのものを表示したい場合は、%%dと書きます。
std::printf("これは%%dです\n");
出力は次のようになります。
これは%dです
%そのものを表示したいときは、%%と書く必要があります。
%dで小数は扱えない
小数の表示には%fを使う
%dは整数用の指定子です。
小数を表示したい場合は、%fを使います。
#include <cstdio>
int main() {
double pi = 3.14;
std::printf("%f\n", pi);
}
出力は次のようになります。
3.140000
次のように、double型の値を%dで表示するのは間違いです。
double pi = 3.14;
std::printf("%d\n", pi); // 間違い
%dはintを期待しますが、実際にはdoubleを渡しているため、未定義動作になります。
scanfではfloatとdoubleで指定子が異なる
小数の入力では、scanfの書式指定子にも注意が必要です。
floatに入力する場合は%fを使います。
float f;
std::scanf("%f", &f);
doubleに入力する場合は%lfを使います。
double d;
std::scanf("%lf", &d);
一方、printfでdoubleを出力する場合は%fを使います。
double d = 3.14;
std::printf("%f\n", d);
printfとscanfでは、同じ小数でも指定子の使い方が異なる場合があるため注意が必要です。
C++ではstd::coutを使うことも多い
std::coutでは%dを使わない
C++では、printfではなくstd::coutを使って出力することも多いです。
#include <iostream>
int main() {
int x = 10;
std::cout << x << '\n';
}
出力は次のようになります。
10
std::coutでは、%dのような書式指定子は使いません。
次のように書くと、%dがそのまま文字列として表示されます。
std::cout << "%d";
出力は次のようになります。
%d
std::coutでは、出力したい値を<<でつなげて書きます。
int x = 10;
std::cout << "x = " << x << '\n';
出力は次のようになります。
x = 10
std::cinでは&を付けない
C++では入力にstd::cinを使うことも多いです。
#include <iostream>
int main() {
int x;
std::cin >> x;
std::cout << x << '\n';
}
std::cinでは、scanfのように&xとは書きません。
std::cin >> x;
と書きます。
scanfでは&x、std::cinではxと書く点に注意しましょう。
printfとstd::coutの違い
printfは書式指定で細かく制御できる
printfは、%dや%05dのような書式指定子を使って、表示形式を細かく制御できます。
int x = 7;
std::printf("%03d\n", x);
出力は次のようになります。
007
このように、桁数や0埋めなどを簡潔に指定できます。
std::coutは型に応じて出力できる
std::coutは、値の型に応じて出力してくれるため、%dや%lldのような指定子を自分で選ぶ必要がありません。
#include <iostream>
int main() {
int a = 10;
long long b = 10000000000LL;
std::cout << a << '\n';
std::cout << b << '\n';
}
printfでは型に合った書式指定子を選ぶ必要がありますが、std::coutではその手間が少なくなります。
ただし、表示形式を細かく整えたい場合は、std::coutでもマニピュレータなどを使う必要があります。
C++20以降のstd::format
std::formatを使う方法もある
C++20以降では、std::formatを使って文字列を整形する方法もあります。
#include <format>
#include <iostream>
int main() {
int x = 10;
std::cout << std::format("x = {}", x) << '\n';
}
出力は次のようになります。
x = 10
std::formatでは、%dではなく{}を使って値を埋め込みます。
std::format("x = {}", x);
これは、printfより型安全に書式付き文字列を扱える方法です。
ただし、C++20に対応している環境でも、コンパイラや標準ライブラリのバージョンによってはstd::formatが使えない場合があります。
%dでよくある間違い
型に合わない値を渡す
最も注意したいのは、書式指定子と実際の型を合わせることです。
long long x = 10000000000LL;
std::printf("%d\n", x); // 間違い
これは%dがintを期待しているのに、long longを渡しているため間違いです。
正しくは次のように書きます。
long long x = 10000000000LL;
std::printf("%lld\n", x);
scanfで&を忘れる
scanfでよくあるミスが、&を忘れることです。
int x;
std::scanf("%d", x); // 間違い
正しくは次のように書きます。
int x;
std::scanf("%d", &x);
scanfでは、入力された値を書き込む場所が必要なので、変数のアドレスを渡します。
%dの数と引数の数が合っていない
次のコードも間違いです。
std::printf("%d %d\n", 10);
%dが2つあるのに、値が1つしかありません。
正しくは次のように書きます。
std::printf("%d %d\n", 10, 20);
std::coutで%dを使おうとする
std::coutでは%dは使いません。
int x = 10;
std::cout << "%d"; // xは表示されない
このコードでは、%dという文字列がそのまま表示されます。
std::coutで整数を表示したい場合は、次のように書きます。
int x = 10;
std::cout << x;
まとめ
%dはint型の10進整数用の指定子
%dは、printfやscanfで使われる書式指定子です。
printfでは、int型の値を10進数で表示します。
int x = 10;
std::printf("%d\n", x);
scanfでは、10進整数を入力してint型の変数に保存します。
int x;
std::scanf("%d", &x);
printfとscanfでは渡すものが違う
printfでは値を渡します。
std::printf("%d", x);
scanfではアドレスを渡します。
std::scanf("%d", &x);
この違いは非常に重要です。
型に合った書式指定子を使う
%dは基本的にint型用です。
longなら%ld、long longなら%lld、std::size_tなら%zuを使います。
int a = 10;
long b = 20;
long long c = 30;
std::size_t d = 40;
std::printf("%d\n", a);
std::printf("%ld\n", b);
std::printf("%lld\n", c);
std::printf("%zu\n", d);
書式指定子と型が合っていないと、未定義動作になる可能性があります。
初心者向けに一言でまとめるなら、%dは「printfやscanfでint型の10進整数を扱うための指定子」です。
まずは次の2つをしっかり覚えておくとよいです。
std::printf("%d", x); // xの値を表示する
std::scanf("%d", &x); // 入力された値をxに保存する
以上、C++の%dについてでした。
最後までお読みいただき、ありがとうございました。
