ICFPの方もいよいよ画像の修復に取りかかっていますが、なかなか進みません。
C言語の標準はISOとかJISで決まっています。標準ではないのですが使ってて便利だと思った方言というか、Microsoft独自仕様をいくつか紹介します。
(1) 名前なしのunion(struct)メンバー
正式にはなんというのか知りません。普通unionのメンバーには必ず名前をつけます。
例えば、これだとメンバーはu.x.a、u.x.b、u.yの3つです。名前なしの場合はstructのxを省略できます。
この場合、u.a、u.b、u.yのようにアクセスできます。.xを省略できるわけです。structでも、あいまいにならない限りは同じことができます。
あくまで方言なので、あまり使っていいものではないと思いますが、ついつい使ってしまいます。どういう時に使うかというと、最初の3つはメンバーが同じだけど、残りが違うみたいなときに使います。
みたいな感じです。
(2) 長さ0の配列
Cでは長さ0の配列は許されないことになっています。int a[0]みたいなのです。
これは、可変長データを作るときに使っています。
例えば、長さの後にcharが可変長続くみたいなデータのヘッダです。データを格納する領域自体はmallocで取りますが、ポインタを一回経由しなくていいので便利です。
メモリ確保はheader *p = (header *)malloc(sizeof(header) + サイズ);みたいなかんじです。データへのアクセスはp->sizeとp->sみたいな感じになります。
javaだと最初からあります。byte a = new byte[サイズ]とすれば、a.lengthでサイズが取れるサイズ可変配列になります。
長さ0配列を使わないとすると
のように配列側をポインタにします。この場合、ヘッダとデータはメモリとして連続しないことになります。
長さ0にこだわらなくても、とりあえず1ということにしておくのもありですが、実際に長さが0のときに無駄なメモリが必要なことになります。
(3) SEH
これはwindowsの構造化例外ハンドラという仕組みです。__try節の後に必ず__finally節が実行されることが保証されています(たぶん)。リソースの確実な解放を行うために使っています。
上の例だと__try節の中でファイルとメモリを確保して、__finally節で解放しています。__try節から脱出するときは必ず__finally節を実行します。例えばreturnしても__finally節は実行されます。
また、普通のCコードだとmallocに失敗したときはfcloseしてからreturnするとかしないといけませんが、エラー処理というかif ~ returnが出てくるたびにリソース解放するのは面倒です。
一応、gotoを使えば同じようなことができます。
というわけで、悪の道は甘い蜜の味ということで、ついつい使ってしまう方言を紹介してみました。可変配列については、C99だとmallocを使わなくても作れるということみたいですが、手持ちのコンパイラ(VC++6.0)はもちろん対応していません。
C言語の標準はISOとかJISで決まっています。標準ではないのですが使ってて便利だと思った方言というか、Microsoft独自仕様をいくつか紹介します。
(1) 名前なしのunion(struct)メンバー
正式にはなんというのか知りません。普通unionのメンバーには必ず名前をつけます。
union { struct { char a, b; } x; int y; } u;
例えば、これだとメンバーはu.x.a、u.x.b、u.yの3つです。名前なしの場合はstructのxを省略できます。
union { struct { char a, b; }; int y; } u;
この場合、u.a、u.b、u.yのようにアクセスできます。.xを省略できるわけです。structでも、あいまいにならない限りは同じことができます。
あくまで方言なので、あまり使っていいものではないと思いますが、ついつい使ってしまいます。どういう時に使うかというと、最初の3つはメンバーが同じだけど、残りが違うみたいなときに使います。
struct header { ... }; struct type1 { struct header; 残り1 }; struct type2 { struct header; 残り2 };
みたいな感じです。
(2) 長さ0の配列
Cでは長さ0の配列は許されないことになっています。int a[0]みたいなのです。
これは、可変長データを作るときに使っています。
typedef struct { int size; char s[0]; } header;
例えば、長さの後にcharが可変長続くみたいなデータのヘッダです。データを格納する領域自体はmallocで取りますが、ポインタを一回経由しなくていいので便利です。
メモリ確保はheader *p = (header *)malloc(sizeof(header) + サイズ);みたいなかんじです。データへのアクセスはp->sizeとp->sみたいな感じになります。
javaだと最初からあります。byte a = new byte[サイズ]とすれば、a.lengthでサイズが取れるサイズ可変配列になります。
長さ0配列を使わないとすると
typedef struct { int size; char *s; } header;
のように配列側をポインタにします。この場合、ヘッダとデータはメモリとして連続しないことになります。
長さ0にこだわらなくても、とりあえず1ということにしておくのもありですが、実際に長さが0のときに無駄なメモリが必要なことになります。
(3) SEH
これはwindowsの構造化例外ハンドラという仕組みです。__try節の後に必ず__finally節が実行されることが保証されています(たぶん)。リソースの確実な解放を行うために使っています。
FILE *fp = NULL; char *p = NULL; __try { fp = fopen(ほにゃ); if(fp == NULL) __leave; p = malloc(うにゃ); if(p == NULL) __leave; } __finally { if(fp != NULL) fclose(fp); if(p != NULL) free(p); }
上の例だと__try節の中でファイルとメモリを確保して、__finally節で解放しています。__try節から脱出するときは必ず__finally節を実行します。例えばreturnしても__finally節は実行されます。
また、普通のCコードだとmallocに失敗したときはfcloseしてからreturnするとかしないといけませんが、エラー処理というかif ~ returnが出てくるたびにリソース解放するのは面倒です。
if(p != NULL){ fclose(fp); return; }
一応、gotoを使えば同じようなことができます。
というわけで、悪の道は甘い蜜の味ということで、ついつい使ってしまう方言を紹介してみました。可変配列については、C99だとmallocを使わなくても作れるということみたいですが、手持ちのコンパイラ(VC++6.0)はもちろん対応していません。