TL;DR
printfで赤色をつけたい場合は以下のように記述します。
printf("\x1b[031mHello, World!\x1b[0m\n");
はじめに
C言語でコーディングしているとき、標準出力に色をつけたいことが多々あると思います。私自身も大学の課題やシェルの実装をしているときなどにそういう気持ちになりました。
今回はC言語のprintfで色をつける方法、さらに掘り下げてSGR1コマンドについて調べた結果を残しておこうと思います。
printfで文字・背景色を変える
C言語のprintfで文字・背景色を変えるには、\x1b[
または \033[
を記述したのち、<Pn>m
で制御を行います。具体的には以下の通りです。
printf("\x1b[031m"); // 文字色を赤色にする
printf("Hello, World!\n"); // 赤色の'Hello, World!'が出力される
printf("\x1b[0m"); // 設定をリセットする

後述しますが、最後の \x1b[0m
を記述することで設定した属性をすべて解除することができます。この記法による動作はOSに組み込まれているAPIを利用するものであるため、プログラム中で設定した属性はこの別のプログラムにも影響を与えます。そのため、設定した属性はプログラム内で必ず解除するようにした方がいいと思います。また、設定した属性を個別で解除することもできます。詳細は、対応している制御コード一覧のSGR部分を参照するといいです。その他にも、以下のような<Pn>で制御ができます。
文字装飾・文字色の制御
<Pn> | 動作 |
---|---|
0 | 文字属性をすべて解除 |
1 | 高輝度/太字に設定 |
2 | 低輝度に設定 |
3 | イタリックに設定 |
4 | 下線をつける |
5 | 低速点滅 |
6 | 高速点滅 |
7 | 文字色と背景色を反転 |
8 | 文字色を背景色と同じにする |
9 | 打ち消し線をつける |
21 | 2重下線をつける |
30 | 文字色を黒に設定 |
31 | 文字色を赤に設定 |
32 | 文字色を緑に設定 |
33 | 文字色を黄色に設定 |
34 | 文字色を青に設定 |
35 | 文字色をマゼンタに設定 |
36 | 文字色をシアンに設定 |
37 | 文字色を白に設定 |
38;2;r;g;b | 文字色をR:r, G:g, B:b で指定する |
38;5;Ps | 文字色を0-255の範囲で用意された色番号 Ps に設定する |
39 | 文字色を標準にする |
90-97 | 文字色を30-37に対応する高輝度色に設定する |
背景色の制御
<Pn> | 動作 |
---|---|
40 | 背景色を黒に設定 |
41 | 背景色を赤に設定 |
42 | 背景色を緑に設定 |
43 | 背景色を黄色に設定 |
44 | 背景色を青に設定 |
45 | 背景色をマゼンタに設定 |
46 | 背景色をシアンに設定 |
47 | 背景色を白に設定 |
48;2;r;g;b | 背景色をR:r, G:g, B:b で指定する |
48;5;Ps | 背景色を0-255の範囲で用意された色番号 Ps に設定する |
100-107 | 背景色を40-47に対応する高輝度色に設定する |
動作一覧
私の環境2では以下のように表示されました。006の高速点滅はあまり対応されてないそうです。また、090以降の高輝度色の設定も上手く設定されませんでした。

#include <stdio.h>
#define ESC 0x1b
#define CSI 0x5b
int main(void)
{
int sgr[110];
int flag = 0;
int index = 0;
for (int i = 0; i <= 9; i++) sgr[index++] = i;
sgr[index++] = 21;
for (int i = 30; i <= 48; i++) sgr[index++] = i;
for (int i = 90; i <= 97; i++) sgr[index++] = i;
for (int i = 100; i <= 107; i++) sgr[index++] = i;
index = 0;
for (int i = 0; i < 11; i++){
int flag = 0;
for (int j = 0; j < 10; j++){
int Pn = i * 10 + j;
if (Pn != sgr[index]) continue;
if (flag == 0){
flag = 1;
printf("%3d- : ", i * 10);
}
index++;
printf("%c%c%d%c", ESC, CSI, Pn, 'm');
printf("%03d", Pn);
printf("%c%c%d%c ", ESC, CSI, 0, 'm');
}
if (flag) printf("\n");
}
return 0;
}
このプログラムは少し変な書き方をしていますが、普通に 3. printfで文字・背景色を変える のように書くか、以下のようにひとまとめにして書いても大丈夫です。
printf("\x1b[031mHello, World!\x1b[0m\n");
ANSIエスケープシーケンス
エスケープシーケンスという言葉をよく耳にすると思います。文字しか入力できない環境下で、画面制御や表示できない文字を入力するために生み出されたものがエスケープシーケンスです。printfで改行をするための \n
や、ヌル文字として使われる \0
もエスケープシーケンスになります。
printfで色を変える際、\x1b
や \033
という文字を入力しました。これは「エスケープ処理を開始しますよ」という意味のコードで、ANSIエスケープコード、またはANSIエスケープシーケンスと呼ばれ、ESCと略されることがほとんどです。ESCに対応するASCII文字コードが16進数で1B, 8進数で33になるため、これを記述しているのがC言語です。Shell ScriptでもANSIエスケープシーケンスを利用することができ、\e
でエスケープ処理を始めることができるようです。
ANSIエスケープシーケンスを用いれば、カーソル移動、カーソル点滅、画面クリアなど様々な動作を行うことができます。詳しくは、コンソールの仮想ターミナル シーケンス等を参照されるといいと思います。この1つにCSI3シーケンスが存在し、これを使うことでSGRコマンドを呼び出し、コンソールに出力する文字に色をつけることができるようになります。
ESC(0x1B)に続けて左角括弧の「[
」(0x5B)を入力することでCSIシーケンス処理を開始します。動作一覧で記述したソースコードのdefineはこれを指定したものでした。CSIシーケンスにはSGRコマンドと呼ばれるものがあり、コンソール出力文字のグラフィック設定を行うことができます。ANSIエスケープシーケンスで以下のように記述することでSGRが呼ばれます。
ESC[<Pn>m
// ESC(エスケープコード、エスケープ処理開始) + [(CSIシーケンス開始) + <Pn>(パターン値) + m
SGRコマンドというよりは、「上記のANSIエスケープシーケンスの記法をSGRと略称する」と捉えた方が正しいかもしれません。
参考文献・サイト