C言語では,配列とポインタに密接な関係があります.
まず,先週のおさらいから.
データのメモリアドレスを指し示す(ポイントする)ための変数
配列の名前は,じつは,配列の最初の要素を指すポインタです.たとえば,
int a[4];
と定義した場合,変数aは要素a[0]へのポインタです.
他の要素を呼び出すには,ポインタに1づつ加えていきます.ポインタ変数に対しては整数の加算と減算が可能です.変数の方によるメモリー上の大きさの違いは自動的に計算されます.
例で見てみると,
配列 | ポインタ |
#include <stdio.h> void main() { char src[20] = "Thank you."; int i; i = 0; printf("文字列="); while(src[i] != 0x00){ printf("%c", src[i]); i++; } } |
#include <stdio.h> void main() { char src[20] = "Thank you."; char *p; p = src; printf("文字列="); while(*p != 0x00){ printf("%c", *p); p++; } } |
何をやっているプログラムか理解できますか?
ここで,Thank you.の3文字目の"a"を表示したい場合はどうしたらよいか考えてみよう.
printf("%c", *p + 2);
で正しいでしょうか.じつは,これは間違いです.*p + 2という演算は,ポインタpの指している所にある値に2を加えるということです.正しくは,
printf("%c", *(p + 2));
となります.
入力されたアルファベットの小文字の文字列をabc順に並べ替えるプログラムを,ポインタを使って書き直そう.
#include <stdio.h> void main() { char s[256], t; int n, i, j; //文字列の入力 printf("単語を入力してください\n"); scanf("%s", s); printf("入力された文字列は%sです.\n", s); // 文字数を数える for(i=0; s[i] != 0x00; i++); printf("文字数は,%d文字です.\n", i); n = i; // 並び替え for(i=0; i < n-1; i++){ for(j=i+1; j < n; j++){ if(s[i] > s[j]){ t = s[i]; s[i] = s[j]; s[j] = t; } } } printf("結果 : %s\n", s); }
これまで使ってきた配列の定義方法では,配列の大きさが,プログラムの作成時にすでにわかっている必要がありました(静的なメモリ確保).ポインタを使うと,はじめに配列の先頭アドレスだけ決めておき,大きさはプログラムの実行時に決めることができます(動的なメモリ確保).ココでは,ポインタを用いたメモリの動的確保方法を練習しましょう.
上のプログラムを,動的なメモリ確保に書き換えると...
#include <stdio.h> #include <memory.h> #include <stdlib.h> void main() { char *s, t; int n, i, j; s = (char *)malloc(sizeof(char)*256); //ここで,はじめてメモリを確保する //文字列の入力 printf("単語を入力してください\n"); scanf("%s", s); printf("入力された文字列は%sです.\n", s); // 文字数を数える for(i=0; s[i] != 0x00; i++); printf("文字数は,%d文字です.\n", i); n = i; // 並び替え for(i=0; i < n-1; i++){ for(j=i+1; j < n; j++){ if(s[i] > s[j]){ t = s[i]; s[i] = s[j]; s[j] = t; } } } printf("結果 : %s\n", s); free(s); //動的に確保したメモリは,必ず解放する }
動的に確保したメモリは,使い終わったら,解放する必要があります.最後のfreeを忘れると,プログラムが終了してもメモリが確保されたままになるので,だんだんコンピュータの動きがおかしくなります.(メモリーリーク)
自宅のWindowsPCで,大学で使っているものとほとんど同じCコンパイラを使うことができます.ボーランド社のホームページから,Borland C++ Compiler 5.5をダウンロードし,インストールするだけです.