キモイ、マカーウザい、厨、言われるのは承知の上

最近ね、マック使うのやめて本格的にLinuxユーザになろうかと思ってたんだけど、Apple Expoの講演会を見て考えが変わった。俺Appleについていくよ。

http://stream.apple.akadns.net/

かなり長いmovieなので、片手間にみるのをお推めする(俺はプログラム書きながら聞いてた)。もうね、感動したよ。特に検索機能であるSpotlightとか、RSSをあざやかにサポートしたSafariを見て、ため息が出てしまった。やっぱインターフェースって大事だな。
Apple製品の良いところってのはいろんな道具の連帯感だと思うのね。その有名な例がiPodでしょ。パソコンに溜めた音楽をそのまま持ち運べる。使用法やプレイリストといったものはすべてiTunesと同期していて、さらにiCalを利用してスケジュールを同期したり、メールアドレスも同期できる。この講演を見ると未来のMacは加速度的にあらゆるソフトが連帯している。

例えば、この講演の中のDemoを例に挙げてみよう。1つめはアドレスブックを開いて、誕生日が30日以内の人を捜し。見つけたひとりをクリックして、その人から(メール等で)送られてきたファイルをハードディスク全体から瞬時に検索するというもの。2つ目はSafariWebブラウザ)で売り上げ全米ベスト10である楽曲を検索、1クリックでiTunesを開き、デモミュージックを聞く(無料)。

上手く説明出来ないけど、この連帯感は結構感動する。今まではアプリケーションって単体で使うものだったけど、こうやって全部が繋がるだと思うんだ。

あぁ、うまく説明できないや。気が向いた人はこの講演会を見てよ。時間無い人は開始35分ぐらいからみても良いかも(前半はOpenGLについてなので、ちょっとマシンスペックにものを言わせた感がある)。

バーチャルキーボード

バーチャルキーボード、予約開始 | スラド

す、凄い。

デスクトップ用としては今のところ普通のキーボードでいいかなと思うものの、例えば、携帯と連系したりすると非常に便利。販売ページでタイプ中の動画が見れるので、それを見て欲しいのだけど、そこに出てくるキーボード投影装置がそのまま携帯だったらどんなに嬉しいか。ちょっとスペースがあればキーボードでメールが送れるよ。

自宅で使うときも専用のマウスパッドならぬキーボードバッドを用意して、そこにバーチャルキーボードを投影すれば、f,j等の印もつけられるし、多少のクリック感も得られるでしょう。

欲しい。

死ぬ程コーディングした気がする

今日一日(13:00 - 23:00)ひたすら自作ソフトのコーディングしてました。それはもう凄い集中力で。思い返して「俺にしては凄い集中力だなぁ」と思ったのは

  1. コーディング中、水分、食料、一切無し
  2. 途中、休憩無し(つまり、10時間座ってました)
  3. コーディング→コンパイルの周期が長い(スクラッチから一応の完動状態まで、一気にやった部分もある)

個人的には3が嬉しい。デバイスドライバカーネルに直結するプログラムを書いている人は一発完動コーディングが普通らしいですが、安定した環境でぬくぬくとしている俺はテストファーストが基本で、コーディング→コンパイル→テストを淡々と繰り返すことが多いのです。

でも、rootにsuid&daemonにする予定のプログラムなので、テストが不充分だと恐い。

UNIX 用語 由来/読み方辞書 version 1.6 (Feb 13 1995)

上記サイトのdeamonの読み方を引用

"daemon" と同義。 悪魔とか守護神、鬼、鬼神という意味だが、UNIXdaemon は"守護神"というのが一番あっている。 「なんか難しい事やろうとすると、出てくる便利な奴」 ということで [どらえもん] という読み方もある。

(´Д` )

FAMのサンプルコード


http://members.jcom.home.ne.jp/j-klein/src-box/famsample.c

FAM(File Alteration Monitor)の日本語情報が少ないので、ちょっとサンプルコードを書いてみた。あんまり有名じゃないのかな、FAMって。

FAMはセキュリティホールになりかねないので、最新のものを利用することをお推めする。さらに危険性を理解していないのであれば、famの-Lオプションを使用して、ローカルからのみ監視を可能にするべき。

【追記】

凄いはずかしいバグがあったので、修正。

【さらに追記】

バグを修正。

select()でブロックして、FAMNextEvent()で変更通知を受け取るんだけど、その間にFAMPending()を入れて、ループしないと同時に来たイベントを取りこぼします。

BrainFuckソース生成プログラム

http://members.jcom.home.ne.jp/j-klein/src-box/2brainfuck.c

標準入力から文字列を読み込んでBrainFuckソースコードに変換します。当然、馬鹿みたいに++++++...とASCIIコードの数だけ繰り返すのではなく、出来る限り短くなるように最適化します(しようとします)。

例えば次のCによるHello, WorldをBrainFuckに変換してみます。

int
main(int argc, char *argv[])
{
    printf("Hello, World\n");
    return 1;
}

BrainFuckにすると……

 >>+++[<+++++[<+++++++>-]>-]<<.+++++.++++++.-------.>++++[<--->-]<.>++++[<++>-]
 <.+++++.>>++[<+++++[<------->-]>-]<<.>>++++[<++++[<++++>-]>-]<<+.+++++.++++++.
 >>++++[<+++[<------->-]>-]<<.>>++++[<++++[<++++>-]>-]<<+.>++++[<++++>-]<+.----
 -------.----.>+++++[<----------->-]<.>++++[<--->-]<.>++++++[<+++++++++++>-]<+.
 +++++.-------.>++++[<++++>-]<+.>>>+++[<+++[<+++[<--->-]>-]>-]<<<-.>++[<+++++>-
 ]<.>+++++[<+++++++++++>-]<.>++++[<++++>-]<+.-----------.>+++[<+++++>-]<.>>+++[
 <+++[<--->-]>-]<<.++.>>++[<+++++[<----->-]>-]<<--.>>>+++[<+++[<+++[<+++>-]>-]>
 -]<<<+.-----------.++.>+++[<--->-]<.+++++.++++++.>++[<------->-]<.>>++++[<+++[
 <----->-]>-]<<--.------.>>++++[<+++[<+++>-]>-]<<++.>++++[<+++++++>-]<+.+++++++
 ..+++.>++++++[<----------->-]<-.>++++[<--->-]<.>+++++[<+++++++++++>-]<.>++++[<
 ++++++>-]<.+++.------.>++++[<-->-]<.>++++[<-->-]<.>++++++[<+++>-]<.>>+++[<++++
 +[<----->-]>-]<<-.+++++++.>++++++[<+++>-]<.>+++++[<+++++++++++>-]<.>++++[<--->
 -]<-.>+++[<+++++>-]<.+.---.----.>+++++++[<----------->-]<-.>++++[<++++>-]<+.>+
 +[<+++++>-]<.>++++++[<+++++++++++>-]<.

となるわけです。これで、CとBrainFuckで同時にHelloWorldを実現できました(笑)。もちろん、これを実行して、コンパイルできます。

適当に作ったので、ソース汚いのは勘弁してくださいな。


【追記】

関連してhttp://members.jcom.home.ne.jp/j-klein/software/bfm/もアップデートしました。これを利用すると上記のBrainFuckのソースを実行して、CのHello, Worldにもどすことが出来ます。

# 古いバージョンのBFMは改行処理がダメだったので、うまくCのソースに戻りません。現在のバージョン(version 1.0.0)ならばバッチリ戻ります。

またベンチマーク

ベンチマーク厨とでも呼んで下さい。

参照:http://proglang-0.ten.thebbs.jp/1079174593/

このスレッドでちょっと興味を持ったので、char配列の初期化について調べてみた。このスレッドに書いたこととも重複するけど、まとめの意味です。Cで文字列を初期化(空文字列)にするときは以下のような方法が考えられます。

(1) char str[1024] = {0};
(2) char str[1024] = "";
(3) char str[1024]; str[0] = '\0';

はじめに言っておきますが、ダントツで(3)が最速です。というか、そもそも意味が違います。(1),(2)はそれぞれstr配列の領域すべてを0で初期化しますが、(3)は最初の要素のみ初期化します(文字列的にはこれでOK)。

1,000,000回上記3通りの初期化をループしたところ結果は

(1) 1.14 sec
(2) 0.43 sec
(3) 0.01 sec

コンパイルは[gcc -O2 benchmark.c]としました。

となりました。もはや結果はどうでもよいです。文字列の初期化ってあんまり使わないし(大抵は明示的にstrncpyやsnprintfなどで具体的な文字を代入してしまうので、初期化は必要無い)、必要があるなら(3)でOKでしょう。見た目がうざったくに見えるなら

#define initstr(s) s[0] = '\0'
char str[1024];
initstr(str);

とすれば良いでしょう。むしろ気になったのはなんで(1)があんなに遅いのかってこと。アセンブラに落してみたらこうなりました(一部抜粋)

    subl    $1036, %esp
    pushl   $1023
    movb    .LC0, %al
    movb    %al, -1032(%ebp)
    pushl   $0
    leal    -1031(%ebp), %eax
    pushl   %eax
    call    memset

おぉい、なんでmemset呼んでるんだい? アセンブリ言語ってあんまり流暢じゃないんだけど、もっと上手いやり方ありそうだけどなぁ。ちなみに(2)はこうなる。

    cld
    pushl   %edi
    movl    $256, %ecx
    leal    -1032(%ebp), %edi
    xorl    %eax, %eax
    subl    $1028, %esp
    rep
    stosl
    movl    -4(%ebp), %edi

やっぱ、奇麗だね。(1)の方をrep stoslで置き換えてみたけど、あんまり速くならなかった。もしかして、memsetが問題なんじゃなくて、movb .LC0, %alのほうが問題。ともかく餅は餅屋で、配列の初期化は配列の初期化用の構文使うのが良い、と。