ゴルフの話ではないです(ゴルフに役立たないとは言っていません)。
C言語のwrite
関数は、unistd.h
で宣言された、ファイルディスクリプタを通じて書き込む関数です。その宣言は以下のようになっています。
ssize_t write(int fd, void* buf, size_t len)
コードゴルフであればfd
に変なファイルディスクリプタを渡したりするところですが*1、今回はそういう話ではないです。
次に変なものを渡せるのは、buf
です。ここに変なポインタを渡すと、len
が0
でなければエラーになり、write
関数の返り値は-1
になります。
errno
は、14
、つまりEFAULT
にセットされます。
「len
が0
でなければ」なので、len
が0
なら正当です。write
関数の返り値は0
になります。
一見意味のない行為に思えますが、どうもfflush
の実装に使えるようです。実際、軽量libc実装のmuslでは、このテクニックが使われています。
(該当箇所引用)
/* If writing, flush output */ if (f->wpos != f->wbase) { f->write(f, 0, 0); if (!f->wpos) { FUNLOCK(f); return EOF; } }
エミュレータでこのコードを動かした時、おかしな挙動になっていて苦労したという話でした。
システムコールエミュレータが「ポインタbuf
が未割当の領域を指していておかしい!」と早合点する実装になっていたのです。
*1:read関数の第一引数に0(stdin)ではなく1(stdout)を渡して読み込まないというのは常套手段ですが、write関数でこういうことをやるのはあまり見たことがない気がします。不勉強なだけかもしれません。