N88-BASIC、アセンブラ、Cでポインター (5回目)

2023/1/25(水)
N88-BASIC、アセンブラ、Cでポインター (5回目)
 
C言語にポインターが存在する意味が
 
文字列中のアルファベットの小文字を
大文字に変換するプログラムを作ることで
 
何となく分かるようにするシリーズです
 
 
今回はC(言語)で
ポインターを使ったプログラムの紹介です
プログラムと解説はコメント(/* … */)を見て下さい

BASICのアドレス(POKE,PEEK,VARPTRなど)
を使ったプログラムや
アセンブラを理解していれば
より簡単に理解できると思います

blg~.zip中のptr005.cです
 
#include <stdio.h>     /* printf等使用の為 */
void main(void)       /* mainから実行     */
{
  char* p;        /* p = a (aは&a[0]) */
  char  a[256];      /* 255文字+終端'\0' */
 
  printf("? ");
  gets_s(a, 256);     /* 文字列入力      */
  printf("%s\n", a);   /* 文字列表示       */
  for (p = a; *p; p++)  /* *p != '\0'繰返し */
  {
    if ('a' <= *p && *p <= 'z')
    {
      *p -= 'a' - 'A';
    }
  }
  printf("%s\n", a);   /* 文字列表示        */
  gets_s(a, 256);     /* キー入力待ち     */
}
 
gets_s(a, 256);
がエラーとなる場合は(多少動作は異なりますが)
scanf_s("%s", a, 256);
を使用して下さい
 
ポインターの説明
char* p;
のpがポインター(アドレスを入れる変数)です
 
メモリー内容が次のような時
0xB000:0x01
0xB001:0x02
p = 0xB000;としておくと
*pは0x01になります(*pはアドレスpの中身)
p[0]と*p、p[1]と*(p+1)は同じです
 
本来は
char *p, *q;
などと書きますが
*pと*q(pとqの中身)はchar型だという宣言です
p,qはchar型を指すアドレスを入れる変数
つまりchar型へのポインターです
 
しかし、個人的にこの書き方が分かりにくいので
char*をchar型へのポインター宣言という解釈して
char* p;
と書いています 

注意点は
char* p,q;

char *p,q;と解釈され、qはポインターではなく
char型になりますので
char* p;
char* q;
と書くようにしています
 
char c; c = 'A';として
p = &c;とするとcのアドレス('A'が存在するアドレス)
がpに入り*pは'A'になります
&は変数の中身がしまわれているメモリーのアドレスです
 
プログラム中のaはchar型の配列変数で
メモリー中に次の様に存在するとします
 
0xB000:'1'
0xB001:'2'
0xB002:'a'
0xB003:'b'
0xB004:'\0'
0xB005:0x??

a[0]は'1'で&a[0]は0xB000です
p = &a[0];でpに0xB000が入りますので
*pは'1'になります
配列変数の変数名はアドレスなので
p = a;としても0xB000が入ります
これで
*p,*a,p[0],a[0]は全て同じ'1'です
*(p+1),*(a+1),p[1],a[1]は全て同じ'2'です
p++;(p = p + 1と同じで1増加する)とすれば
*pは'2'になります(pは0xB001となる為)
a++;はエラーです
(a自体は変数ではなくアドレスという数値で
2++;としているのと同じ為)
 
前回と今回の違いは
文字列aを0から数えてi番目を見る時
pにa+iが入っているとすると
a[i]と*pの違いです
 
pにa+2(0xB002)が入っていると
a[2]と*pは同じ'a'になります
 
a[i]はa+iを計算して中身*(a+i)を見ますが
*pはa+iの計算なしで中身*(a+i)を見ることが
出来る分処理速度が速くなります
 
配列a[i]は見やすい代わりに遅く
ポインターp(*p)は見にくい代わりに速い
ので、場合によって使い分ければ良いと思います
 
また、アセンブラはポインターと同じ考えで
作られている事が多く、C言語のポインターは
速度の速いアセンブラのような書き方が出来る
ようにするために存在していると思います
 
C言語が速い理由はアセンブラに近い
(これを低級言語という)書き方ができるためです
アセンブラから遠い(これを高級言語という)ほど
遅くなる傾向がある様です
 
ちなみにBASICはインタプリタなのでアセンブラに
変換されずに、インタプリタが実行しているため
極端に遅いのです
BASICコンパイラはアセンブラ(機械語、マシン語)に
変換しているため少し?マシ?
 
このシリーズの2~3回目のBASIC(メモリーとアドレス)
とアセンブラ(Z80)が理解できる方にとっては
ポインターは難しくないと思います
 
アドレスを使ったBASICはアセンブラに変換し易かった様に
ポインターを使ったCもアセンブラに変換し易いのです
 
 
C、インラインアセンブラは、
Cコンパイラーなどを準備しておいて下さい
例、Microsoft Visual Studioなど
 
windowsのconsoleアプリは実行終了後
ウインドウが閉じてしまうので
最後にキー入力待ちを入れています
使用している入力関数は
Microsoft Visual Studio以外では
代替え関数に変更する必要があるかも
しれませんがご了承下さい
 
 
blg~.zip(ptr005.c)は
以下のリンクからダウンロードできます

https://ulprojectmail.blogspot.com
Readme.txtを読んで遊んで下さい













このブログの人気の投稿

NEWS

N88-BASICでゲーム (1回目)