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をダウンロードし,インストールするだけです.