C++の%dについて

AI実装検定のご案内

C++で見かける%dは、主にprintfscanfなどのC言語由来の入出力関数で使われる書式指定子です。

たとえば、次のように使います。

#include <cstdio>

int main() {
    int x = 10;
    std::printf("%d\n", x);
}

出力は次のようになります。

10

この場合、%dは「ここに整数を10進数で表示する」という意味を持ちます。

ただし、%dはC++の文法そのものではありません。

"%d"は文字列の一部であり、それをprintfscanfなどの関数が特別な意味として解釈しています。

そのため、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歳です

%ddは、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つ目の%da、2つ目の%dbが対応します。

重要なのは、%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では&が必要

scanfint型の変数に値を入力する場合は、変数名の前に&を付けます。

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を返します。

整数として読み取れない入力が来た場合は、失敗として扱えます。

printfscanfでの%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ではxscanfでは&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);  // 間違い

%dintを期待しますが、実際にはlong longを渡しているため、未定義動作になります。

正しくは%lldを使います。

long long x = 10000000000LL;
std::printf("%lld\n", x);

charshortは整数昇格される

charshortprintfに渡すと、多くの場合intに昇格して渡されます。

たとえば、次のコードは一般的に問題ありません。

short s = 10;
std::printf("%d\n", s);

shortprintfに渡されるときに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で表示すると、true1false0として表示されます。

bool flag = true;
std::printf("%d\n", flag);

出力は次のようになります。

1
bool flag = false;
std::printf("%d\n", flag);

出力は次のようになります。

0

これは、boolprintfに渡されるときにintへ昇格されるためです。

ただし、C++らしく表示するなら、std::coutstd::boolalphaを使う方法もあります。

#include <iostream>

int main() {
    bool flag = true;
    std::cout << std::boolalpha << flag << '\n';
}

出力は次のようになります。

true

整数型ごとの書式指定子

よく使う整数用の書式指定子

%d以外にも、整数型にはさまざまな書式指定子があります。

書式指定子対応する型意味
%dint符号付き10進整数
%iint整数
%uunsigned int符号なし10進整数
%ldlonglong型の符号付き10進整数
%luunsigned longunsigned long型の符号なし10進整数
%lldlong longlong long型の符号付き10進整数
%lluunsigned long longunsigned long long型の符号なし10進整数
%xunsigned int16進数、小文字
%Xunsigned int16進数、大文字
%ounsigned int8進数
%zustd::size_tsize_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++では、sizeofstd::string::size()の戻り値としてstd::size_tがよく使われます。

std::size_tprintfで表示する場合、%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_tintとは異なる型なので、%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);  // 間違い

%dintを期待しますが、実際にはdoubleを渡しているため、未定義動作になります。

scanfではfloatdoubleで指定子が異なる

小数の入力では、scanfの書式指定子にも注意が必要です。

floatに入力する場合は%fを使います。

float f;
std::scanf("%f", &f);

doubleに入力する場合は%lfを使います。

double d;
std::scanf("%lf", &d);

一方、printfdoubleを出力する場合は%fを使います。

double d = 3.14;
std::printf("%f\n", d);

printfscanfでは、同じ小数でも指定子の使い方が異なる場合があるため注意が必要です。

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では&xstd::cinではxと書く点に注意しましょう。

printfstd::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);  // 間違い

これは%dintを期待しているのに、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;

まとめ

%dint型の10進整数用の指定子

%dは、printfscanfで使われる書式指定子です。

printfでは、int型の値を10進数で表示します。

int x = 10;
std::printf("%d\n", x);

scanfでは、10進整数を入力してint型の変数に保存します。

int x;
std::scanf("%d", &x);

printfscanfでは渡すものが違う

printfでは値を渡します。

std::printf("%d", x);

scanfではアドレスを渡します。

std::scanf("%d", &x);

この違いは非常に重要です。

型に合った書式指定子を使う

%dは基本的にint型用です。

longなら%ldlong longなら%lldstd::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は「printfscanfでint型の10進整数を扱うための指定子」です。

まずは次の2つをしっかり覚えておくとよいです。

std::printf("%d", x);   // xの値を表示する
std::scanf("%d", &x);   // 入力された値をxに保存する

以上、C++の%dについてでした。

最後までお読みいただき、ありがとうございました。

よかったらシェアしてね!
  • URLをコピーしました!
  • URLをコピーしました!
目次