「かっこつける話」(2005/12/22 (木) 23:22:39) の最新版変更点
追加された行は緑色になります。
削除された行は赤色になります。
C言語は、やたらと括弧を使う。
関数だけでなく、マクロにも、演算子にも、キーワードにも。
特に紛らわしいのは、演算子とキーワード。
sizeof()が、関数だと思って(あるいはそんなことすら考えずに)使ってる人、結構いる。
これは、演算子であって、+とか-とかと同じモノなのだ。
したがって、sizeof()でサイズを取得する処理は、基本的にコンパイラが行う。このレベルで行うからこそ、配列のサイズなんてものが取得できるのだ。前にも書いたように、C言語は「先っぽ」しか知らないのだから。
unsigned char ucaHoge[100]:
unsigned char* ucpPiyo = malloc((size_t)100);
と宣言したとき、どちらも100バイトの領域の「先っぽ」をさしている。
決定的に違うのはucaHogeは100バイトから増えも減りもしない、つまりソースがコンパイルされる時点で大きさが決定しているのに対して、ucpPiyoは処理によってサイズが変わる(領域を確保しなおす)可能性がある。
これらに対してsizeof()でサイズを取得しようとすると、ucaHogeが100を返すのに対してucpPiyoはポインタ型変数のサイズ(32bit環境だと4)を返す。sizeofは「演算子」で、静的な演算はコンパイルの時点で計算され数値に置き換えられるからだ。
sizeofに()がついているのでまるで魔法のようにサイズを取得できそうな関数って感じだけど、そうではないのだ。
ここら辺のことは、まあある程度C言語触った人なら知ってると思うんだけど。
それでも、まだまだ落とし穴はある。
例えば静的な配列でも、サイズを取得できない場合がある。
aaa.c というファイルで
unsigned char ucaHoge[100];
を宣言したとして、bbb.c でも使いたくなった時、
extern unsigned char ucaHoge[];
としてしまうとそのソースコード内ではサイズが判らないため、コンパイラはsizeof(ucaHoge)で「先っぽ」のサイズ(ポインタのサイズ)を返す。意外と、これでハマったりする人を見かける。
また、文字列も中位が必要。
char* cpMoji1 = "Hello!\n";
と宣言したとき、
sizeof(cpMoji1) と sizeof("Hello!\n")は一致しない。
前者はポインタのサイズを返し、後者は文字列のバイト数(NULL文字を含む)を返す。
文字列リテラルはポインタだと思ってる人も多い(これは結構熟練者にも多い)が、実は静的かつconstな配列なのである。
これらのことはsizeof()が演算子だと理解していればそんなにややこしい話ではないのだけれど、なまじ括弧がついてるから騙されやすい。
また、キーワードにつく括弧も要注意。というか、言いたいのはreturnキーワードについてだけと言ってもいいけど(w
関数から帰るとき
return 1;
とする人と
return(1);
とする人がいる。
文法上は、どちらも問題ない。
でも、ミスタイプして
retrun(1);としてしまうとコンパイラはretrunという関数コールだと思ってしまう。この手のミスは、()をつけなければコンパイラがはじいてくれるので見つけやすいんだけれど、そうでないとなかなか見つけにくい。
なので、returnには括弧もつけれるけど、つけない書き方をオススメします。
かっこつけずに、行こう。
C言語は、やたらと括弧を使う。
関数だけでなく、マクロにも、演算子にも、キーワードにも。
特に紛らわしいのは、演算子とキーワード。
sizeof()が、関数だと思って(あるいはそんなことすら考えずに)使ってる人、結構いる。
これは、演算子であって、+とか-とかと同じモノなのだ。
したがって、sizeof()でサイズを取得する処理は、基本的にコンパイラが行う。このレベルで行うからこそ、配列のサイズなんてものが取得できるのだ。前にも書いたように、C言語は「先っぽ」しか知らないのだから。
unsigned char ucaHoge[100]:
unsigned char* ucpPiyo = malloc((size_t)100);
と宣言したとき、どちらも100バイトの領域の「先っぽ」をさしている。
決定的に違うのはucaHogeは100バイトから増えも減りもしない、つまりソースがコンパイルされる時点で大きさが決定しているのに対して、ucpPiyoは処理によってサイズが変わる(領域を確保しなおす)可能性がある。
これらに対してsizeof()でサイズを取得しようとすると、ucaHogeが100を返すのに対してucpPiyoはポインタ型変数のサイズ(32bit環境だと4)を返す。sizeofは「演算子」で、静的な演算はコンパイルの時点で計算され数値に置き換えられるからだ。
sizeofに()がついているのでまるで魔法のようにサイズを取得できそうな関数って感じだけど、そうではないのだ。
ここら辺のことは、まあある程度C言語触った人なら知ってると思うんだけど。
それでも、まだまだ落とし穴はある。
例えば静的な配列でも、サイズを取得できない場合がある。
aaa.c というファイルで
unsigned char ucaHoge[100];
を宣言したとして、bbb.c でも使いたくなった時、
extern unsigned char ucaHoge[];
としてしまうとそのソースコード内ではサイズが判らないため、コンパイラはsizeof(ucaHoge)で「先っぽ」のサイズ(ポインタのサイズ)を返す。意外と、これでハマったりする人を見かける。
また、文字列も中位が必要。
char* cpMoji1 = "Hello!\n";
と宣言したとき、
sizeof(cpMoji1) と sizeof("Hello!\n")は一致しない。
前者はポインタのサイズを返し、後者は文字列のバイト数(NULL文字を含む)を返す。
文字列リテラルはポインタだと思ってる人も多い(これは結構熟練者にも多い)が、実は静的かつconstな配列なのである。
これらのことはsizeof()が演算子だと理解していればそんなにややこしい話ではないのだけれど、なまじ括弧がついてるから騙されやすい。
また、キーワードにつく括弧も要注意。というか、言いたいのはreturnキーワードについてだけと言ってもいいけど(w
関数から帰るとき
return 1;
とする人と
return(1);
とする人がいる。
文法上は、どちらも問題ない。
でも、ミスタイプして
retrun(1);としてしまうとコンパイラはretrunという関数コールだと思ってしまう。この手のミスは、()をつけなければコンパイラがはじいてくれるので見つけやすいんだけれど、そうでないとなかなか見つけにくい。
なので、returnには括弧もつけれるけど、つけない書き方をオススメします。
かっこつけずに、行こう。
表示オプション
横に並べて表示:
変化行の前後のみ表示: