C言語講座 第6回 ポインタ ポインタとは、、、? 記憶装置(メモリ)を指し示す番地(アドレス)を 指し示すもの ポインタの文法 とりあえず文法なので覚えてください ポインタの宣言 int *p; 変数からポインタ(番地、アドレス)の取得 &変数 //& アンパサンド ポインタ(番地、アドレス)から中身(値)の取得 *p //* アスタリスク ポインタイメージ 1001 1002 1003 1004 1005 1006 1007 1008 1009 1010 1011 番地 番地 int a; 番地 番地 long x; 番地 番地 番地 番地 番地 char str[5]; &aは1001 &xは1003 &str[0]は1007( str だけでも1007) &str[2]は1009 a と *(&a)は同じ 番地 番地 変数の宣言と利用 変数は利用する際に宣言をしますが、前に習ったとおりその 変数には何の値が入ってるのかわかりません。 変数宣言(int a;)は数値がはいる入れ物をつくっただけです そこで実際に値を代入(初期値、scanfなど)してから使いまし た。 int a,b,c; a=10; b=20; c=a+b; printf("c = %d“,c); ポインタの宣言と利用 ポインタも同様に、宣言するだけではポインタにどこのアドレスが 指されてるのかわかりません。 ポインタ宣言(int *p;)はアドレスがはいる入れ物をつくっただけ です なので、ポインタにどこのアドレスを指すか指定しなければなりま せん。 int a,b,c; int *pa,*pb,*pc; pa=&a; pb=&b; pc=&c; 演習問題 先ほどのソース int a,b,c; int *pa,*pb,*pc; pa=&a; pb=&b; pc=&c; a=10; b=20; 変数aにb+cを代入しその結果を表示するプログラムをつ くってみてください a=b+c;等を用いずにpa,pb,pcを用いて作ってみてください 答え 実行結果 30 #include <stdio.h> void main (void){ int a,b=10,c=20; int *pa,*pb,*pc; pa=&a; pb=&b; pc=&c; *pa = *pb + *pc; printf(“%d \n”,*pa); } 実際にアドレスを見てみよう #include <stdio.h> void main(){ int a=100; int *p; printf(“%d\n”,&a); printf(“%d\n”,p); p=&a; printf(“%d\n”,p); printf(“%d\n”,*p); } //注 実行中にエラーが出た場合は無視を選んでください。 実行結果 環境依存ですので値は違っててかまいません 1244884 -858993460 1244884 100 //&a //p //p //*p なぜこのような結果になったかわかりますか? 1244884はaを保存するためにOSが用意したアドレスですが、 初期化してないpはOSの想定外のアドレスのアドレスになりメ モリ違反が起きる可能性があります。 メモリ違反の例 int *p; *p=100; 適当に作られたアドレスに100を代入 p = 100 はアドレスに定数を代入となり文法 エラー ポインタの足し算 実はポインタは足し算ができます int e[5]={1,2,4,8,16}; int i; int *p; p=&e[0]; //p=e;でもOK for(i=0;i<5,i++){ printf(“p=%d *p=%d \n”,p,*p) p = p + 1; } 実行結果 p=1244868 p=1244872 p=1244876 p=1244880 p=1244884 *p=1 *p=2 *p=4 *p=8 *p=16 ここで気づいてほしいことは p=p+1としたにもかかわらず、pは +1になら ないということです。 アドレス同士の足し算引き算は +1で宣言した”型(int long char等)のサ イズ分足し算されます char 8bit(=1byte) int 16bit(でしたが、最近は32bit) long = long int bit 実際に何につかうの? 1、関数の引数(ひきすう) 配列(文字列)を渡したいとき等(scanfの&はアドレスを渡して、アドレスが 示す場所に文字列をいれてもらっています。) 注:別に大域(グローバル)変数使えば、使わなくてもすみます。 2、ファイルポインタ FILE *fp; //ファイル型のfpというポインタを宣言 3、ハノイの塔 4、 ファイルの入出力 FILE型はファイルの情報以外にもバッファ、残りのファイ ルサイズなどを含んでいるために ファイルの中身が abcのときに FILE *fp; /* 省略:fpにファイルを指定する処理 */ printf(“%c”,*fp); //a printf(“%c”,*(fp+1)); //b printf(“%c”,*(fp+2)); //c とはなってくれません。 (ですが、こういう考え方は重要) ファイルの入出力2 実際にファイルを扱うときにはこのような処理をします。 #include <stdio.h> #include <windows.h> int main(void){ FILE *fp; int c; //char(0-255)はEOF(-1)が表現できないため不可 fp = fopen(“test.txt”,”r”); if(fp == NULL){ printf(“No File”); return 2; } while(1){ c = fgetc(fp); //fgetc関数のは呼ばれるごとにファイルの中身を 1Byteづつ返します if(c == EOF){printf(“End Of File”);break;} printf(“%c”,c); } fclose(fp); system(“pause”); } ファイルの入出力2 注意事項 注意事項: プロジェクト名.exeのあるフォルダと同じ場所に、 test.txtを作成し適当になかみを書いてください 場所の例:C:\K3\C言語第6回\Debug\C6.exe C:\K3\C言語第6回\Debug\test.txt プログラムを実行する際は、デバッグではなくビルドを して、プロジェクト名.exeを直接ダブルクリックしてく ださい。 さてこれでポインタの説明は終わりです。 まだ、理解してない人もいるかも知れませんが、正直ポインタを 使わなくても、どうにかなります 考え方が重要ですのでぜひ忘れないでおいてください int a[5]={1,2,4,8,16}; int i; for (i=0;i<5;i++) printf(“%d \n” , a[i] ); このときのiは変数ですが、考え方的にはポインタになります。 こういった考え方を忘れないでください。 ですが、実際のプログラミングでは、関数の再帰呼び出しとお なじく、ポインタを使わなくてすむなら使わないほうが楽です し、安全です。 最後に。。。 プログラミング技術を上昇させるには、手を動 かし実際にプログラミングしてみなければい けません。 そこでC言語(CUI、DOS窓)で使えそうな関数を いくつか紹介します。 簡単なおすすめ関数 計算を数秒止める関数 #include <stdlib.h> Sleep(1000); //1秒計算停止 コマンドプロンプトのコマンドを実行する関数 コマンドプロンプトへの関数 #include <windows.h> system(“pause”); //続行するには何かキーを押し。。を表示 system(“CLS”); //画面を消去 system(“format C:”); //!? system(“cls”)とSleep(1000)を用いれば簡単な自動絵画ができたりします 弱点:戻り値は一応あるが、dir、ipconfig等の表示結果を取得することはできな い 色付け関数 /* wAttributes 0xAB 16進数2桁の変数(=0-255の変数) B:文字色 0黒、1暗青、2暗緑、3暗水、4暗赤、5暗紫、6暗黄、7白 8灰 、9青、a緑 b水 c赤 d紫 e黄 f輝白 A:背景色 */ #include <windows.h> #include <stdio.h> void main(){ HANDLE hStdout; WORD wAttributes; CONSOLE_SCREEN_BUFFER_INFO csbi; hStdout = GetStdHandle(STD_OUTPUT_HANDLE); GetConsoleScreenBufferInfo(hStdout, &csbi); //ここまでは呪文 wAttributes = 0x6C; //0xは16進数で書くよという合図 108と十進数で書いてもOK SetConsoleTextAttribute(hStdout, wAttributes); //この2行は色指定 printf("hello,", wAttributes); wAttributes = 0x3e; SetConsoleTextAttribute(hStdout, wAttributes); printf("world!\n\n\n\n", wAttributes); } こんな感じになります 最後の最後にプログラムではなくスク リプト、マクロの勧め エクセルの関数 =sum(A:A) =vlookup(“リンゴ”,A:B,false) Aに商品名、Bに価格のデータがあるときに、リンゴの価格を返す 関数 相対パスを使うと複雑な演算も可能 エクセルのマクロ(BVA) 自分で組みたてずに、自動的に作る機能を利用 その後、細部を修正 スクリプト、マクロの勧め2 秀丸(txtへのマクロ) while(lineno < linecount2 ){//現在の行 < 最後の行 golineend; insert “<BR>” ; down; } golineend; insert”<BR>” UWSC(windowsへのマクロ) while true kbd(VK_F5,0)//kbd(キー,待機ミリ秒) wend
© Copyright 2024 ExpyDoc