Trigraph
やっぱりマニアくらいしか知らない仕様があって、例えば C の Trigraph なんてのがあります。
これは、# とか \ とか [] とか無い文字セットしかない場合でも C のコードが書けるようにという ANSI規格化のときに追加された配慮で、以下のような対応になっています。
Trigraph Equivalent ======== ========== ??= # ??/ \ ??' ^ ??( [ ??) ] ??! | ??< { ??> } ??- ~
Digraphs and trigraphs - Wikipedia
この Trigraph を使うと、例えば
#include <stdio.h> int main( void ) { char hello_str[] = "hello,world"; int i; for (i = 0; i < sizeof(hello_str) -1; i++) { printf( "%c\n", hello_str[i] ); } return 0; }
なコードは、
??=include <stdio.h> int main( void ) ??< char hello_str??(??) = "hello,world"; int i; for (i = 0; i < sizeof(hello_str) -1; i++) ??< printf( "%c??/n", hello_str??(i??) ); ??> return 0; ??>
なエレガントなコードに大変身するわけです。(よ、読めない...)
どう考えても これは C の 暗黒面なので、普段気にすることは全くないです。というか知らない方が良い仕様であるわけですが、極々 まれに悪さをしてくれるのです。というのも、Trigraph の置換は コメント中や文字列中でも 行われてしまうので、例えば
// comment???/
で次の行もコメントになっちゃうとか、"??<" みたいな文字列を扱えないとか が起きるわけです。
なので gcc なんかでは Trigraph 置換 はデフォルトで OFF に成っています。で、たまたまこんなコードをビルドすると
#include <stdio.h> int main( void ) { printf( "??<hogehoge??>" ); return 0; }
> gcc main.c main.c:5:11: warning: trigraph ??< ignored, use -trigraphs to enable main.c:5:22: warning: trigraph ??> ignored, use -trigraphs to enable >a ??<hogehoge??>
と怒られて ??? となるわけです。(無視されるので実際の出力は置換されません。良い挙動だー)なお、gcc で Trigraph を有効にするには -trigraphs オプションを付けます。
> gcc -trigraphs main.c > a {hogehoge}
当然怒られないし、出力結果は置換されてしまいます。(いきなりコッチをやられた方が訳がわからなくなるかも)
* * *
こんな風に 実際に使いどころがあるのか非常に怪しい Trigraph ですが、上記の様な問題があるとなれば放って置けません。なので C99 にて あらたに Trigraph の欠点を補う Digraph が導入されました。
Digraph Equivalent ======= ========== <: [ :> ] <% { %> } %: # %:%: ##
....なんでそんなにこだわるのさorz.
でもっ!コレ、意外に結構イけてるんですにゃ。混乱の元だった コメントや文字列リテラルの中での置き換えは無効になってます。そして、なんといっても最大の改善点はコレ
%:include <stdio.h> int main( void ) <% char hello_str<::> = "hello,world"; int i; for (i = 0; i < sizeof(hello_str) -1; i++) <% printf( "%c\n", hello_str<:i:> ); %> return 0; %>
うーん、実に読みやすい(ぉ
イけてるのでgcc も そのままビルドを通してくれます。