浮動小数点数は指数部と仮数部の積で表される。
続きを読む「C言語」タグアーカイブ
C言語でクロージャーを実現したい、あるいは実行時のコード生成によるクロージャー
導入:クロージャーについて
昨今ではクロージャーを使えるプログラミング言語は珍しくなくなった。クロージャーとは、関数の引数だけではなく、外のスコープにある変数を参照できる関数のことである。
例えば、次のJavaScriptコードでは、関数を返す関数 f
を定義している。 f
の中で定義された無名関数は、外側の変数 x
を参照できている。
function f(x) { return function(y) { return x + y; }; }
JavaScriptではネストした関数を使わなくても、bind
メソッドによって同等の処理を記述することができる:
function g(x, y) { return x + y; } function f(x) { return g.bind(null, x); // gの第1引数を束縛する }
残念ながらC言語にはクロージャーはない。関数の中に関数を書けないからだ。
しかし、クロージャーと同等のこと、つまり関数に追加の引数を渡すことはできないのだろうか?
続きを読むC言語のワイド文字入出力 — Windows Console 編
C言語のワイド文字入出力 — MSVCRTの場合
C言語のワイド文字入出力
C言語にはワイド文字で入出力を行う関数が用意されている。
※ワイド文字:C言語のワイド文字 (wchar_t) とは、不憫な子である。Windows だと Unicode のコードポイント1個すら表せない16ビットだったり、Unix だとそもそも使われている気配があまりなかったり(もっぱら UTF-8 か UTF-16 が使われている印象がある)する。2010年代の後半にもなってワイド文字なんぞを真面目に扱うブログというのは時代錯誤も甚だしい。
ワイド文字で入出力と言っても、対象がファイルの場合は最終的にはバイト列を読み書きしているわけで、どこかの段階でバイト列とワイド文字列との変換が行われているはずである。この変換方法はどうやって決まっているのか。あるいは、ワイド文字の入出力関数とバイト列 (char) の入出力関数を混在させるとどうなるのか。
また、Visual C++ や glibc の場合は fopen の第2引数に ,ccs=UTF-8
みたいな文字列を設定できるという謎の仕様がある。これを指定した場合は何が UTF-8 になるのか。
こういった細かい仕様は、ワイド文字自体がオワコンなこともあり、あまり知られていないように思う。少なくとも筆者は知らなかった。というわけで、
- ワイド文字による入出力について、C言語の規格ではどう定められているか
- Visual C++ のランタイムライブラリ (MSVCRT) ではどう実装されているか
- Linux 等で使われている glibc ではどう実装されているか
- macOS 等で使われている BSD libc ではどう実装されているか
浮動小数点数による複素数の演算に関する注意点
コンピューターで複素数を表す時は、通常は実部と虚部の組をそれぞれ浮動小数点数として持つ。
複素数の演算は、数学的には 続きを読む
Visual C++ での C99 complex
最近のVisual C++ではC99もある程度サポートしているらしい。
- C99 library support in Visual Studio 2013 | Visual C++ Team Blog
- C++11/14/17 Features In VS 2015 RTM | Visual C++ Team Blog
- “Our C99 Standard Library implementation is complete, except for …” という記述がある。
上記ブログによると、 complex.h の関数もサポートしているらしい。しかし、コンパイラーは _Complex
型をサポートしていない。_Complex
型をサポートしていないのに、 complex.h の関数をサポートしているとはどういうことか。一体、 complex.h の関数は何を受け取って何を返すのか。
確認のため、次のような簡単な C++ のプログラムを書いてみた。 続きを読む
C言語でなんちゃって2進数リテラル
こういうビットマップ(1ピクセルにつき1ビット)を、整数の配列としてC言語のソースコード中に埋め込みたい:
□□□□□ ■■■■■ □■□■□ □■□■□ ■□□■■ □□□□□
2進数リテラルがあればそれを使うという手があるが、残念ながらC言語には2進数リテラルがない(ちなみに、C++にはC++14から2進数リテラルが入った。また、独自拡張で2進数リテラルが使えるコンパイラーもある)。
というわけで、自分で作ることにした。要件としては
- コンパイル時定数となる
- 桁を空白で区切れる
がある。 続きを読む
C言語の可変長引数マクロで擬似オーバーロード
C99で導入されたプリプロセッサマクロの可変長引数を使って、引数の個数によるオーバーロードっぽいことをするメモ。
参考:
- c – Overloading Macro on Number of Arguments – Stack Overflow
- [C言語] 可変引数マクロの作り方 – Qiita
- 余談 C++ Design: g++とvc++の可変引数マクロの挙動の違い
可変長引数の部分への実引数が0個というのはC言語の規格的にはナシなので、引数が0個の場合には対応しない。(幾つかのコンパイラでは引数が0個でも通るが…)
GCCの場合に0個の引数を処理したい場合、GCC拡張の , ## __VA_ARGS__
みたいなやつを使うといい感じになる。
VC++で
#define CHOOSE(a0,a1,...)
#define hoge(...) CHOOSE(__VA_ARGS__)
という風に書くと、 __VA_ARGS__
の部分が一つの引数(a0
)として関数型マクロに渡ってしまうので、ここに書いたコードでは CHOOSE
→ CHOOSE2
という風にもう一段階噛ませている。
C11の _Generic
とかを使えば引数の型によるオーバーロードもできそうだ。先例: