Restricted Words

なんとなく気が向いた,というか,この手のプログラミングパズルにしては対応言語が多く,C言語もOKというのは珍しいな,ということで解いてみた.

お題

引用する.

標準出力に Hello World と出力するプログラムを作成して下さい。

ただし、数値、文字及び文字列リテラルを解答に含めることはできません。 Perlのqqやqw、Rubyの%Q、%q、%wなども避けたほうが評価が高くなります。 言語仕様をフル活用して下さい!

解法の定石

定石は,数値を得て,その文字コードに変換する. ASCIIコードでなくEBCDICな処理系だったらどうするの? みたいなツッコミは,とりあえず採点環境が OSX だということで無視できる.

この方針だと,1 をどのようにして得るかというのが鍵になる. 出題者の意図は,この定石通りだった. 回答者に送られた解説も引用可とのことなので,出題者の解説から引用する.

・C/C++ 初期化式を持たないグローバル変数はbssセクションに置かれます。main()が実行されるより前に0で初期化されるので、その変数をインクリメントすれば1になります。 また、xorにより0を作り出し、それをインクリメントしても1になります。 もしくは、少なくともx86/x64のgcc/clang上では、sizeof(char)は1です。

もなもな的解法

定石通りに解くのは面白く無い. 他の言語でなく GCC を選ぶからには,GCC なりの解き方で行かねば. なので,このように解いた.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
/*
 * Environment: gcc version 4.2.1 (Apple Inc. build 5666) (dot 3)
 */
#include <stdio.h>

void
Hello(void)
{
  fputs(__func__, stdout);
}

void
konokansuu_wa_space_wo_hyouji__(void)
{
  printf("%c", (int)sizeof(__func__));
}

void
World(void)
{
  puts(__func__);
}

int
main(void)
{
  Hello();
  konokansuu_wa_space_wo_hyouji__();
  World();    
}

__func__ は GCC拡張のビルトインマクロ. 最終的には関数名の文字列リテラルに展開される. しかし,cpp を通した時点ではC言語仕様の数値,文字には展開されない.セーフ.

スペース文字を関数名に含めることは(当然)できないので,一工夫. 関数名を31文字にして,__func__ の sizeof を取った.ナル文字含めて32. これを文字として表示すればスペース文字になる.

言語仕様をフル活用して下さい!

とのことで,GCC の言語仕様を活用. LL系言語だと,シンボルを文字列に変換する機能をよく見かけるけれど,C言語でこの技法を選ぶ奴は少ない…よね.たぶん.

馬脚,もしくは,見直しは大事だよ

なお,出題者からのコメント.

なお、putchar()を使えば”%c”は回避可能です。

確かに.

そういや,学生だった頃も,最後の見直しをしないで提出して,必ず何点か引かれていたよなぁ…. こういうの,何歳になっても,治らんね.