ザビタン開発日記
2009 | 01
2008 | 01 | 02 | 06 | 12
2007 | 10 | 11 | 12
10月 15 (月曜日) 2007
09:34
多次元配列の受け渡し
 
うわー! わかった〜!!!
なまじポインタを理解したつもりになってたのでよけいややこしいく
考えちゃって迷宮めぐりになってしまった!! orz

えっと。まず、配列を関数で渡す定番の方法。

void testkansuu(int a, int b, char hairetu[]){
printf(hairetu[4]);
}

void main(){
char a[9];
a[4] = 'A';

testkansuu(1,2, a);
}

この例ではわかるよね?。配列としてaを丸ごと渡している。これで
受け手である関数testkansuuは配列aを受け取れる。
あとはtestkansuu内で普通に配列として取り出せるわけ。

で、これどういうことかって言うと、

実は hairetu[] は *hairetu と同じ意味になる。
つまり、ポインタによって、配列変数aが格納されているアドレスが
やり取りされているわけ。

そこで気をよくして、多次元配列を送ってみた。


void testkansuu(int a, int b, char hairetu[][]){
printf(hairetu[4][3]);
}

void main(){
char a[9][9];
a[4][3] = 'A';

testkansuu(1,2, a);
}


エラーになっちゃうんだよねぇ・・・
いろいろとこね回したり検索してみると、こういうことすればOKだということが解った。


void testkansuu(int a, int b, char hairetu[][9]){
printf(hairetu[4][3]);
}

void main(){
char a[9][9];
a[4][3] = 'A';

testkansuu(1,2, a);
}


わかる? testkansuuでの引数の定義のところで、配列の後ろのほうの値をあらかじめ設定しておけばコンパイルできるようになる。

・・・でもさぁ。これじゃ、呼び出すMain側からは、a[][]を自由に
設定できないよね。a[2][2]にしたい時もあるかもしれない。
そんな時、いちいち関数の定義を書き換えるってのは・・・。
面倒なだけじゃなくて、バグやミスのいい温床になっちゃうよね?

そこで考え方を変えてみることにした。

そもそも多次元配列なんて存在しないのだ!!

たとえば

  char a[10];
char b[2][5];
int i,j,s;
s=0;

for(i = 0; i <=12; i++){
a[i] = i;
}

for(i = 0; i <= 3; i++){
for(j = 0; j <= 4; j++){
s=s++;
b[i][j]=s;
}
}

こうしたとしよう。仮に変数aが0x100から格納され、変数bは0x200から格納されたと仮定すると・・・


変数a 変数b
┌───┬───┐   ┌───┬───┐
│番地 │ 値 │   │番地 │ 値 │   
├───┼───┤   ├───┼───┤
│0x100 │ 1  │   │0x200 │ 1  │ ← [0][0]  
├───┼───┤   ├───┼───┤
│0x101 │ 2  │   │0x201 │ 2  │ ← [0][1]    
├───┼───┤   ├───┼───┤  
│0x102 │ 3  │   │0x202 │ 3  │ ← [0][2]    
├───┼───┤   ├───┼───┤
│0x103 │ 4  │   │0x203 │ 4  │ ← [0][3]    
├───┼───┤   ├───┼───┤
│0x104 │ 5  │   │0x204 │ 5  │ ← [0][4]   
├───┼───┤   ├───┼───┤
│0x105 │ 6  │   │0x205 │ 6  │ ← [1][0]    
├───┼───┤   ├───┼───┤
│0x106 │ 7  │   │0x206 │ 7  │ ← [1][1]    
├───┼───┤   ├───┼───┤
│0x107 │ 8  │   │0x207 │ 8  │ ← [1][2]   
├───┼───┤   ├───┼───┤
│0x108 │ 9  │   │0x208 │ 9  │ ← [1][3]    
├───┼───┤   ├───┼───┤
│0x109 │ 10  │   │0x209 │ 10  │ ← [1][4]    
└───┴───┘   └───┴───┘

このように、メモリ内部への格納にはなんの差もないのだ!!

だったら、渡された先であるtestkansuu内部では単なる普通の配列
(多次元ではない)と考え、要素数を自前で計算させちゃったって
同じ値が取り出せるんじゃない?。要素の数を引数ででも渡しちゃえばいいんじゃない??

そんなわけで、呼び出し先であるtestkansuuの内部で、a[4][3]を
取り出したいとすると、これでOKとなるよね?

void testkansuu(int a, int b, char *hairetu){

  // a[4][3]を得たい場合は・・・
printf(hairetu[4*3]);

}

void main(){
char a[9][9];
a[4][3] = 'A';

testkansuu(9,9, a); ←要素の数を引数で渡してあげる
}


これで結果は同じことになり、当然コンパイラはエラーを吐かない。
わーーーい!!! ばんざーーい!

・・・あ”
スマソ要素数を渡してあげる必然性ないよねこの例では・・・(^^;
tesukansuu内で連続して取り出したいとかそういう場合の話ね。
 
●uchan@Guest -- 10/17 07:28
僕も引っかかった問題なので、面白いです。ところで、printf(hairetu[4]);ですが、printfはchar型変数を渡せないと思います。

30日を過ぎたBlogにはコメントできません。
10月 14 (日曜日) 2007
14:42
関数化できんかな
 
さて先日背景にパターンを置きました。
こんどはウィンドゥだーーー!
と思ったのですが、そこでも今回のように一定のパターンを敷き詰める
形になりますね。うーん。今回は簡単なfor文でできたけど、ウィンドゥ
や飾りバーなどもその都度計算式を考えるってのも・・・・

そこで、背景埋め尽くしをputfontみたいに関数化できないかと思い、
ちょっとやってみます。(うまくできるかな〜???)

モデルになるのはすぐ上にあったboxfill8かなぁ。
この関数は

  1. vramの番地は?
  2. 画面のx方向の幅は?
  3. 塗る色は?
  4. 開始点のx,y座標は?
  5. 終了点の  〃

こういうパラマータがいる関数だよね?

同じような関数を妄想し、必要なパラメータを考える・・

  1. vramの番地は?
  2. 画面のx方向の幅は?
  3. パターンを格納している番地は?
  4. パターンのx幅、Y高は?
  5. 敷く積める場所の開始点、終了点

・・・とりあえずこんなところかな?
graphic.cの下辺りにとりあえず置いてみて、init_screen8から呼んでみよう。


void ptboxfill8(char *vram, int xsize, int ysize){
int y2,x2;
for (y2=0; y2 <= ysize; y2=y2+4) {
if (y2 % 8 == 0){
x2=1;
}
else{
x2=3;
}
for(x2; x2 <=xsize; x2=x2+3){
vram[y2 * xsize + x2] = 0;
}
}

return;
}

・・・おぉ! うまくいったぞ!??
今はこんなふうに呼んでいるけど

ptboxfill8(vram,x,y);



static char *ptn[8][8] = {
"........",
"........",
"........",
"........",
"........",
"........",
"........",
"........"
};
ptboxfill8(vram,x,y,ptn);

こんなパターンで呼べないかなぁ。えとえと・・・・



あっれぇ〜クソ! 配列を渡すのってポインタじゃないのかな・・・
こんな基礎的な所で引っかかる俺って・・・・orz

・・・ん? まてよ??






 
30日を過ぎたBlogにはコメントできません。
10月 13 (土曜日) 2007
22:15
背景パターン
 
・・・こうしてみますた!








void init_screen8(char *vram, int x, int y)
{
boxfill8(vram, x, COL8_FFFFFF, 0, 0, x - 1, y - 1);

int y2,x2;
for (y2=0; y2 <= y; y2=y2+2) {
for(x2=0; x2 <=x; x2=x2+2){
vram[y2 * x + x2] = 0;
}
}
:
:


・・・うーん・・・網目模様にはなったけど、なんかちょっと
色気ないなぁ・・・・


もうちょっとイジってみてと・・・・・






int y2,x2;
for (y2=0; y2 <= y; y2=y2+4) {
if (y2 % 8 == 0){
x2=1;
}
else{
x2=3;
}

for(x2; x2 <=x; x2=x2+3){
vram[y2 * x + x2] = 0;
}








こうなりますたぁ!!! (^^)
 
30日を過ぎたBlogにはコメントできません。
16:11
まずは見た目
 
どっから手を入れていこうかっていうと・・・

ズバリ! 見た目!(笑

まあ復習と練習を兼ねてまずはそこいらへんからですな。

画面が広過ぎ


ウチのマシンだと、QEMUのVESAが思いっきり効きすぎちゃって
大きくなりすぎなんだよねぇ。800x600くらいがちょうどよさそう。
えーっと。画面の広さを定義してるのが・・・

/haribote/asmhead.nas で行われている。(P280辺り)

VBEMODE EQU を 0x103 (800x600x8bitカラー)に変更〜。

マウスポインタがちょっと・・・


マウスポインタをもうすこしカコヨクしたいなぁ・・・
えっと、マウスポインタは・・・
graphic.c で行われてるね。

"**************..",
"*OOOOOOOOOOO*...",
"*OOOOOOOOOO*....",
"*OOOOOOOOO*.....",
"*OOOOOOOO*......",
"*OOOOOOO*.......",
"*OOOOOOO*.......",
"*OOOOOOOO*......",
"*OOOO**OOO*.....",
"*OOO*..*OOO*....",
"*OO*....*OOO*...",
"*O*......*OOO*..",
"**........*OOO*.",
"*..........*OOO*",
"............*OO*",
".............***"


オリジナルはこうだけど、これを


"*...............",
"*O*.............",
"*OO*............",
"*OOO*...........",
"*OOOO*..........",
"*OOOOO*.........",
"*OOOOOO*........",
"*OOOOOOO*.......",
"*OOOOOOOO*......",
"*OOOOO*****.....",
"*OO*OO*.........",
"*O*.*OO*........",
"**..*OO*........",
"*....*OO*.......",
".....*OO*.......",
"......**........"


こうしますた!!

壁紙?をold Mac風? に・・・


背景。Win95風の単色カラーですが、これをパターンで塗りつぶしてみよう。

背景の緑の部分もシートとして管理されてたはずだよね?
ええと・・・どこだったかな??

あったあった。bootpack.cからinit_screen8をコールしてるね。これが
背景やニセタスクバーの描画をしている。
init_screen8はgraphic.c内にあるからここを書き換えよう。
一番最初の行のboxfill8でズドーンと背景を塗っている。まずは

boxfill8(vram, x, COL8_FFFFFF, 0, 0, x - 1, y - 29);

こんなことして背景を真っ白に。
で、Mac風のパターンで塗りつぶそう。
 
30日を過ぎたBlogにはコメントできません。

Referer  (10)
12:23
ツール類更新
 
えーっと。たしかz_tools内のツール類って、本発売の後に
いくつか更新されてなかったっけ?
さっそくチェック・・・
 
30日を過ぎたBlogにはコメントできません。
01:34
開発開始!
 
さてさて〜。
そんなわけで、THE-BBL OSの開発とまいりましょう。

OS自作本の最終形。harib27fをベースに少しづつ改造してゆこうと。

うーむ。そーいえばBBLって、SF.jpにアカウントもらってるんだよ
なぁ。どうしよう。いい機会だし、ちょっとだけバージョン管理機構
の活用にチャレンジしてみようかなぁ。ベイサイド氏もかなり
便利だと言ってたし・・・。

 
30日を過ぎたBlogにはコメントできません。

Referer  (1)
« 7 8 9 10 11 12 13 14 15 16 (17) » 

PopnupBlog V3 Denali created by Bluemoon inc.