配列とポインタ変数
ブラックボックスにして使うのもよいけども
できれば理解してほしいなと思うわけで
ポインタと配列何が違うか
コンパイラが初期化(メモリの割り当て要するにmalloc)をするかしないかなわけなのだが
どうもこいつがわかりにくいのかなーとおもう
口だけで説明するのは主義に反すので実装をしよう
#include <stdio.h> #include <stdlib.h> struct tst_st { int st_a; int st_b; }; int main(argc,argv) { int inta[5]= {10,20,30,40,50}, *intb; int i; struct tst_st tst_a[5], *tst_b; //ポインタを[5]として初期化 intb = malloc(5 * sizeof(int)); for(i=0;i<5;i++){ //ポインタとしてアクセス *(intb + i)=inta[i] ; } for(i=0;i<5;i++){ //配列としてアクセス printf("%d ",inta[i]) ; printf("%d \n",intb[i]) ; } //ポインタを[5]として初期化 tst_b = malloc(5 * sizeof(struct tst_st)); for(i=0;i<5;i++){ tst_a[i].st_a = i * 100; } for(i=0;i<5;i++){ //ポインタとしてアクセス (tst_b + i)->st_a = tst_a[i].st_a ; } for(i=0;i<5;i++){ //配列としてアクセス printf("%d ",tst_a[i].st_a) ; printf("%d ",tst_b[i].st_a) ; } free(tst_b); free(int_b); return 0; }
アロー演算子(->)と配列の添字([0])は等価です。少なくとも僕の理解では
ただ困ったことに人間の脳は抽象化が大好きで
初期化が必須 と言う部分を忘れる
そして忘れちゃう人はこう言うんだ
「教習所(授業)ではどんな車(ポインタ)でもギアを変えてアクセルを踏めば(添字を付けてアクセスすれば)動く(使える)って習った」
こんな時のベストアンサーは
「ああ確かに動くとも、キーをさしてエンジンをスタート(mallocでちゃんと初期化)させれば」
Cはプログラマにメモリを意識させないように配列っていう抽象化レイヤーを作ったのにわざわざアドレス云々言いたがるのは不思議だね。
んで配列と大きなレジスタ
これはOS内で良く使われるトリックで
メモリーは恐ろしく遅いので4byteでlodeしてbyteごとに処理をしたりする
unionとアトリビュートで固めてね。
実装はこんな感じで
union pack_32bit { unsigned int int_pack; unsigned char char_pack[4]; }__attribute__((packed)); int main(int argv,char **argc) { union pack_32bit test; int i; test.int_pack = 0x80706050; for(i = 0;i<4;i++){ printf("%x ",test.char_pack[i]); } return 0; }
ただこれはエンディアンに絡んでCの移植性を落とすので別途マクロで
移植性の低下を回避するように書いてやらなければならない。
i386で実行すればわかるけれども最下位バイトが一番最初に表示される。
Linuxはその点の考慮がないコードが紛れ込んでいたりする。
最後にハンドラ
これはクラスのポインタにあたるので
new専用のコンストラクタで実体を作って使うのと同様にopenで専用の関数で実体を作る。
という感じだとおもうのだが
飲みながら書いたら眠くなってきたので尻切れとんぼ。
僕の理解は間違っているかもしれないがそしたら誰かがまたトラックバックして
載せるだろう。