Iimaimai17468·2026.06.04

if文を使わずにFizzBuzzをする

C
0

高専時代、C言語FizzBuzzコードゴルフ遊びをしてた時に後輩に教えてもらったやつ

for(int i = 1;i < 100;i++) {
 printf("%d,%s\n",i,"\0____Fizz\0Buzz\0FizzBuzz" + (5 * !(i % 3) + 10 * !(i % 5)));
}

!が実質分岐の役割をしてなくもないが許してください

解説

for分で1から100まで回して、結果をprintfで出力するのは見ればわかるので割愛します。

まず"%d,%s\n" で整数と文字列を出してます。

問題はここですね。

"\0____Fizz\0Buzz\0FizzBuzz" + (5 * !(i % 3) + 10 * !(i % 5))

構造としては、文字列+数値ですが、C言語における文字列は先頭ポインタを指しています。

char *s = "Hello";  // s はアドレス100を指す
s + 0  // アドレス100 → "Hello"
s + 1  // アドレス101 → "ello"
s + 3  // アドレス103 → "lo"

ので、(5 * !(i % 3) + 10 * !(i % 5)) で3で割れるのか5で割れるのかでポインタに数値を足し、出したい文字列を出し分けています。

また、\0は終端文字を表すので、それ以降の文字は出力されません。

// 3で割れる時
// (5 * !(i % 3) + 10 * !(i % 5))) -> 5 * 1 + 10 * 0 -> 5
"\0____Fizz\0Buzz\0FizzBuzz" + 5 = "Fizz\0Buzz\0FizzBuzz" // Fizz が出力される

// 5で割れる時
// (5 * !(i % 3) + 10 * !(i % 5))) -> 5 * 0 + 10 * 1 -> 10
"\0____Fizz\0Buzz\0FizzBuzz" + 10 = "Buzz\0FizzBuzz" // Buzz が出力される

// 3, 5の両方で割れる時
// (5 * !(i % 3) + 10 * !(i % 5))) -> 5 * 1 + 10 * 1 -> 15
"\0____Fizz\0Buzz\0FizzBuzz" + 15 = "FizzBuzz" // FizzBuzz が出力される

// どちらでも割れない時
// (5 * !(i % 3) + 10 * !(i % 5))) -> 5 * 0 + 10 * 0 -> 0
"\0____Fizz\0Buzz\0FizzBuzz" + 0 = "\0____Fizz\0Buzz\0FizzBuzz" // 先頭が終端文字なので何も出力されない

コメント (0)