2014-06-01から1ヶ月間の記事一覧
個人的メモです。データ型モデル char short int long long long void * ILP32 8 16 32 32 64 64 LP64 8 16 32 64 64 64 規格Cごとの接尾語なしの10進定数の型について。 以下のうち、その定数がオーバーフローしないような最小の型が選ばれる*1。 C89 int, …
算術変換の検証をする上で、対象の整数値がsignedかunsignedかを判定するマクロを作成してみました。 #define <limits.h> #define IS_SIGNED(x) ( \ (( (x)>>1)&(1L<<(sizeof(x)*CHAR_BIT-1)))!= \ ((~(x)>>1)&(1L<<(sizeof(x)*CHAR_BIT-1))) ) というものです。このマ</limits.h>…
ついに来ました、ビットシフト。みんな大好きビットシフト。signed型の負数に対する右ビットシフトの結果は処理系依存なので、以下の話はgcc限定ととらえて下さい。まずは、unsigned char型のビットシフトから。 unsigned型のビットシフトは解説するところが…
整数型の値に対して、その下位nビットを取り出す場合、 x & ((1<<n)-1) と書いたりしますが、これって2を法とする剰余(2^nで割った余り)でも表現できないか?と考えたことはあると思います。まず、char/unsigned char型変数の値127に対して、(2^n)-1でマスクをかけてみます。 > char : 127 0111 1111 > char -> int 0000 0000 0000 0000 0000 0000 0111 1111 > c & 0x0F 0000 0000 0000 0000 0000 0000 0000 1111 > unsigned char : …</n)-1)>
汎整数拡張、俗にいう「暗黙のキャスト」はソースコードに出てこないところの挙動なので、C言語上級者でもなかなかに引っかかりやすいトラップだと思います。先日、組込み系の記事で見かけた例ですが…以下コードは、unsigned char型変数をビット反転し、その…
前回は、以下のことを確認しました。 基本形が同じならば、signed/unsigendでキャストしようが、その内部表現(ビット列)は変化しない。 内部表現が同じであっても、その数学的値が同じとは限らない。 今回は、char/unsigned charをint/unsigned intにそれ…
「C言語はポインタが難しい」というのが定説ですが、ポインタは四天王の中でも最弱だと思っています。ポインタ以上に難解なのが、この「汎整数拡張」。インテグラル・プロモーション(integral promotion)とも言います。汎整数拡張の挙動を確認する上で、ビ…
「詳説Cポインタ」p43より。 2.2.1 malloc関数の使い方 (略) void* malloc(size_t); malloc関数はsize_t型の引数を1つ取ります。この型は1章で扱いました。引数に値を指定する際には、 注意が必要です。負の値を指定した場合には、問題となります。システ…
配列の添字指定は「人間にとっての分かりやすい表現」であって、配列概念など知ったこっちゃない処理系は「ベースアドレス(先頭要素へのポインタ値)+要素サイズ*要素番号」という計算式で、配列の各要素にアクセスしているのです。配列が「先頭要素へのポ…
ポインタ・配列についての「分かりやすい説明」を目指すことは、ネットの解説でも多くみかけますが、ポインタと配列は、根本的に日常とはかけ離れたアクロバティックな頭の使い方を求められるので、日常的直観との距離を縮める比喩的説明(住所を書いたメモ…
頭の体操として、二次元配列の各要素を参照するコードを、いろんな書き方で書いてみようと思います。いまさら二次元配列?と思うなかれ。こういう当たり前のコードを、1ステップずつ意味を理解した上で、高速でコーディングできるのも、ひとつの技術力だと思…
関数の引数に配列型変数を指定した場合、関数内の当該仮引数はポインタ型変数に型調整される(正確には、配列の先頭要素へのポインタ値が格納されたポインタ型変数に型調整される)。これが多次元配列になると、どうなるだろう。二次元配列とは、T型配列のT…
sizeof演算子の続きです。 関数のプロトタイプ宣言で配列型を指定された引数は、関数の仮引数ではポインタ型として扱われる、というお話です。 1 /* sizeof_func.c */ 2 #include <stdio.h> 3 4 void func(char buf[]){ 5 printf("sizeof(buf)@func = %zu\n", sizeof(</stdio.h>…
sizeof演算子について、いろいろ試してみました。アセンブリコードを見てみると、sizeofオペランドの式はコンパイル時に定数に置換されるか、sizeofの計算に影響を与えない数式の場合、式自体が翻訳時に捨てられているのが分かります。 00000000004004e3 <main>: i</main>…
Linuxではカーネルがinitを起動する際、以下の順番でパス検索し、はじめに見つかったinitを起動する。 /sbin/init /etc/init /bin/init /bin/sh initのPIDは1。 PIDの最大値は32768(/proc/sys/kernel/pid_max)。 PIDの割当ては単調増加方式で、サイクリッ…
例えば、1秒ごとに「.」(ドット)を表示するプログレスバー的なものを考えてみます。 1 /* progress.c */ 2 #include <stdio.h> 3 #include <unistd.h> 4 5 int main(int argc, char *argv[]) 6 { 7 int i; 8 9 for(i=0; i<10; i++){ 10 printf("."); 11 sleep(1); 12 } 13 14 </unistd.h></stdio.h>…
CSVファイルのコメント行・空行をスキップし、コメント部を削除して、各レコードを配列に格納するスクリプトです。 ・行"aaa,bbb ccc,ddd"を分割して、2列目の値「bbb ccc」がスペースで区切られないこと。←これは対応したが ・"aaa,,ccc"で、「ccc」が3列目…