2013-09-01から1ヶ月間の記事一覧

【配列とポインタ】第9回 配列とは概念である

前回までで、メモリ上のデータの参照/代入に必要な情報は、「位置」「長さ」「解釈の仕方」だ、と書きましたが、逆に言うと、その3つさえ分かれば、何でもできてしまいます。それがC言語の恐ろしいところですが…以下は、アドレス0x804A024に位置する1バイト…

【配列とポインタ】第8回 そもそも変数とは何か?(2)

今回は、変数の残りのキモである「データの長さ」「データを正しく解釈する方法」についてです。データの長さ前回は、メモリ上の特定領域にアクセスするための「位置情報」(アドレス)について書きました。この位置情報を使って、特定領域にアクセスすると…

【配列とポインタ】第7回 そもそも変数とは何か?(1)

今まで、さんざんポインタと配列をいじり倒しながら試行錯誤してきましたが、そろそろ「そもそも変数とは何か?」という本質論について考える時が来たようです。プログラミングの入門書によくある説明で、変数とは「番号のついた箱」と言われます。データ格…

【配列とポインタ】第6回 char **argvを実装してみる(2)

前回の擬似argv実装を、いい感じにリライトしてみた(つもり)です。 マジックナンバーがかっこ悪いですが、動的配列の機能はC99からなので使用禁止。使用する変数は、以下の通り。 変数 役割 char string 文字列の実体を格納する領域 char *arg_plist[] 各…

【配列とポインタ】第5回 char **argvを実装してみる(1)

main()の引数である、「char **argv」の擬似変数「char **argv2」を実装してみます。 引数文字列の実体をスタックの連続領域に作成し、 各文字列の位置情報を管理するポインタ配列を作成し、 ポインタ配列の位置情報をargv2に格納する という流れでやってい…

【配列とポインタ】第4回 式の展開規則(配列・ポインタ編)

式の展開規則実際のコーディングでは、扱う配列はたかだか二次元配列までがほとんどなので、一次元・二次元配列の展開手順は反復練習で身体で覚えてしまって、それ以上の多次元配列になれば、以下の展開規則を再帰的に当てはめて展開していけばいいかと思い…

【配列とポインタ】第3回 間接演算子は関数である

今まで見てきたように、間接演算子*の作用は、以下のようにまとめられると思います。char型配列の配列arrが以下のようにあるとき、 +------+------+------+------+------+ arr | arr0 | arr1 | arr2 | … | arrN | +------+------+------+------+------+式中…

【配列とポインタ】第2回 配列へのポインタ

式中において、ポインタに間接演算子*をつけると、参照先の値に展開される…というのは当たり前ですが、int型変数へのポインタに*をつけると、int型の値に展開される。 char型変数へのポインタに*をつけると、char型の値に展開される。 ポインタ型変数へのポ…

【配列とポインタ】第1回 配列

C言語中級者にとっての鬼門と言っても過言ではない、配列とポインタ絡みのところが、いつまで立ってもモヤモヤして気持ち悪い!ので、何回かに分けて、基礎からまとめてみたいと思います。宣言と初期化char型配列の宣言時の初期化子には、以下例のように文字…

sizeof演算子

以下について、sizeofでサイズを調べてみます。 文字リテラル 空文字 文字列リテラル char型配列 int型配列 int型二次元配列 int型二次元配列の最上位次元の先頭要素の間接参照 int型二次元配列の間接参照 char型配列の集合を管理するポインタ配列 char型配…

constの修飾対象

間接演算子*と、constが混在した場合の変数宣言について、まとめてみました。 # syntax constの修飾対象 1 const chat *p ポインタの参照先オブジェクト 2 char * const p ポインタ変数そのもの 3 const char * const p 1かつ2 ちなみに、以下のような記述も…

配列要素を参照するシンタックスバリエーション

C言語では、以下のシンタックスは、すべて'B'に展開される。 (文字列リテラル"ABCDE"の格納領域の先頭アドレスを、0x8048560と仮定します。) # syntax 1 "ABCDE"[1] 2 ((char *)0x8048560)[1] 3 1["ABCDE"] 4 (&"ABCDE")[0][1] 5 0[(&"ABCDE")][1] 式中の…

argvのメモリ構造

main関数のargvの構造がどうなっているのか調べてみた。 1 #include <stdio.h> 2 3 int main(int argc, char *argv[]) 4 { 5 int i; 6 7 printf("%p : argc %d\n", &argc, argc); 8 printf("%p : argv %p\n", &argv, argv); 9 printf("%p : argv+1 %p\n", &argv+1, *(</stdio.h>…

T型の配列

「ポインタ虎の巻」を読んでいたら、今更ながら、こんな盲点に気づかされた。 /* !!! 間違ったコード例 */ int data[3][5]; int **p; p = data; /* Syntax Error !!! */ 二次元配列の値を、ポインタのポインタ変数に代入しているので、なんとな〜く正しそう…

free(3)

#include <stdlib.h> void free(void *ptr); free(3)で注意すべきは、 引数ptrの値は、malloc、calloc、またはreallocの返却値と同じでなければならない。 すでに解放された領域に対してfree(3)すること(二重解放)は動作未定義である。 NULLポインタに対するfree(3)</stdlib.h>…