こんにちは。ねこがくれです。
OUCC Advent Calender 2025に参加したことを忘れており、当日に慌てて書いています。
カレンダーはこちらです!
私がメインで使っている言語はC言語です。
つまり、私が大好きな言語ではあるのですが、非常に面倒くさい仕様や、わけのわからない仕様がたくさんあります。これは日ごろの鬱憤を晴らそうぜ、という記事です。
Cに対しての文句
まぁ、日ごろからの鬱憤なんて腐るほどあります。
配列とポインタのあいまいな関係性とかです。
配列を関数に渡すと勝手にポインタに退化する上、sizeofの結果も変わる。絶対躓くポイントですよね。
これがわたしはいちばん嫌いです。
まぁ、慣れたらそんなことなくなるんですけど...。
文字列処理(苦行)
C言語における文字列は、ただのchar配列にnull終端がついただけです。
は?となる方もいるでしょう(特にRustaceanとか)
まぁ、要は長さ情報を持ってません。つまり安全に処理しようと思ったらstrlen()で計算する必要があります。これがO(n)(確か)なので、ループで使うとすごく処理速度が低下します。
あと、文字列の比較には==が使えません。strcmp()を使わないといけない。これマジで嫌いです。めんどくさい。しかもstrcpy()やstrcat()はバッファオーバーフローの温床です。
...あ、strncpy()を使っても、null終端されない場合があるという罠もありますね♪ヤッハハァ♪
マクロ(という名の悪魔)
マクロも厄介です。括弧を忘れただけで演算子の優先順位がおかしくなりますし、デバッガでステップ実行できないので、バグの原因究明が本当に難しいです。
#define MAX(a, b) a > b ? a : b
int x = MAX(1 + 2, 3); /* 1 + 2 > 3 ? 1 + 2 : 3 → 3になる */
こういうバグを何度も経験しました...
で、大体全然違うところを変えまくって結局マクロやんけ!となって泣きます。
エラー処理もうちょっと統一してくれ
エラーハンドリング系は統一されていません。関数によって戻り値が-1だったり、NULLだったり、0だったり。errnoをチェックしないといけない関数もある。例外機構がないので、エラーチェックのコードで本質的なロジックが埋もれてしまいます。
正直、例外処理はせめてプロジェクトで統一しないと、本当にしんどくなります。
標準ライブラリもうちょっと増やして...
動的配列、ハッシュマップ、リンクリストといった基本的なやつすら標準ライブラリにありません。毎回自分で実装するか、サードパーティライブラリを探すか。で、実装をしようとすると、void*だらけになって型安全性が失われます。
それでもCを書く理由
...とまあ、文句を言い出したらキリがないのですが、それでもC言語を使い続けているのには理由があります。
低レイヤを直接触れる感覚、メモリレイアウトを完全にコントロールできるという支配感。
これらはC言語でしか得られない栄養だと思います。
あとC言語書けるってなんかかっこよくないっすか?
鬱憤は溜まりますが、まぁ、それも含めてC言語。明日も私はCを書き続けるでしょう。
最後に
こんな記事を読んでいただきありがとうございました。
中二なのですごい読みづらい文章だったと思います。
ところで、今私はliteCoreというOSを開発しています。
こちらからスターいただけるとうれしいです!