画像(logo)

HOME/[C言語 入門]小学生でもわかるC言語2 目次/六日目 ポインタ3

広告

[C言語 入門 小学生でもわかるC言語2]
六日目 ポインタ3

広告

↓2016年02月29日発売↓

12歳からはじめる ゼロからのC言語 ゲームプログラミング教室

目次へ戻る

配列とポインタ

今回は配列とポインタの関係を見ていきましょう!

まずは配列の先頭部分のメモリアドレスをポインタに入れて、そこから何番目というように他の場所を指定してみます。

/*六日目 プログラム1*/
#include <stdio.h>

int main(){
	int hairetu[5] = {10,9,8,7,6};
	int *p;
	
	p = &hairetu[0];

	printf("配列の先頭アドレス = %x\n",&hairetu[0]);
	printf("pに保存されたアドレス = %x\n",p);
	printf("先頭に保存されてる数字 = %d\n\n",*p);

	printf("配列番号2のアドレス = %x\n",&hairetu[2]);
	printf("p + 2 = %x\n",p + 2);
	printf("配列番号2の内容 = %d\n",hairetu[2]);
	printf("*(p + 2) = %d\n",*(p + 2));

	return 0;
}

■実行結果■

画像(ce_6_1)

ポインタを使って、間接的に他の配列番号の内容を確認します。

int hairetu[5] = {10,9,8,7,6};

こちらの配列の先頭部分のアドレスをポインタに保存します。

int *p;	
p = &hairetu[0];

ポインタを宣言する時は変数の頭に「*」アスタリスクですね。

そしてアドレスを使う時は頭に「&」アンパサンドでした。

先頭部分のアドレスなので「&hairetu[0]」ですね。

では次にそのポインタのアドレスを計算して、他の配列番号の内容を確認してみます!

先頭アドレスから「+何番目?」というような感じで計算します。

「p + 0」だと先頭アドレス

「p + 1」だと「hairetu[1]」のアドレス

「p + 2」だと「hairetu[2]」のアドレス

こんな感じで計算します。

そして頭に「*」アスタリスクをつければ内容を確認できるので

*(p + 2) = 8;

こんな感じですね。

ちなみに、このかっこを外してこうしてみると

*p + 2 = 12;

ポインタ変数「p」の内容の方にたし算してしまうので注意しましょう。

何度も言いますが、

アドレス→「p」

内容→「*p」

です。

とにかく覚えましょう。

続いて内容の方も間接的にいじってみたプログラムです。

/*六日目 プログラム2*/
#include <stdio.h>

int main(){
	int hairetu[5] = {10,9,8,7,6};
	int *p;
	
	p = &hairetu[0];

	printf("配列番号2のアドレス = %x\n",&hairetu[2]);
	printf("p + 2 = %x\n\n",p + 2);

	printf("配列番号2の内容 = %d\n",hairetu[2]);
	printf("保存されてる内容に+2 = %d\n",*(p + 2) + 2);

	return 0;
}

■実行結果■

画像(ce_6_2)

こんな感じになりますね。

広告

何か変だよ、アドレス計算

一つ目のプログラムの実行結果をもう一度見てください。

先頭アドレスp = 39fe30
配列番号2番目のアドレス = 39fe38

ここに疑問を感じた方は16進数をきちんと理解していますね!

16進数といっても数字の進みは一緒なので、

p = 39fe30;
p + 2 = 39fe32;

とならなきゃ何か変だよ!となるワケです!

これははるか昔に習った

数字を使う時は「int」

文字を使う時は「char」

という変数を宣言する時のアレの事をもう少し知る必要があります!

「int」や「char」の話

こちらのサイトでは

数字専用が「int」

文字専用が「char」

というように紹介したと思います。

実はですね。特に専用ではなく、例えば

「int」だったら「メモリ4つ分」

「char」だったら「メモリ1つ分」

の場所を使いますよ!

というように、使う場所の大きさを指定していたのです!

それで「int」は「4つ分メモリ」、この大きさでポインタ変数も宣言しているので

int *p;
p = 39fe30;
p + 1 = 39fe34;
p + 2 = 39fe38;

のように4つとびに進んでいたのです!

注意

さきほどの「「int」の場合はメモリ4つ分」は使うコンパイラによって、変わる場合があります。メモリ2つ分とるコンパイラもあります!

C言語をみんなが使えるように、規則を決めましょう!と昔やっていた頃にごちゃごちゃっとなって、こんな統一感がない事になったらしいのですが・・・。

こういうもんだと覚えましょう!

「char」の場合はほとんどのコンパイラでメモリ1つ分が用意されます!

なぜに文字の方が小さいのかというような理由は。話せば長いので

こういうもんだと覚えましょう!

アドレス自体を動かす

ここまでは最初に保存したアドレスを基準としてそこから何番目というように指定しました。

次はアドレスそのものを動かして値を確認したり変更したりしてみます。

/*六日目 プログラム3*/
#include <stdio.h>

int main(){
	int hairetu[5] = {10,9,8,7,6};
	int *p;
	int i;
	
	p = &hairetu[0];

	printf("pに保存されたアドレス = %x\n",p);
	printf("pの内容 = %d\n\n",*p);

	p++;

	printf("p++後\n");
	printf("pに保存されたアドレス = %x\n",p);
	printf("pの内容 = %d\n\n",*p);

	*p = 1000;

	printf("*p = 1000後\n");
	for(i=0;i<5;i++){
		printf("%d",hairetu[i]);
		printf(" ");
	}

	printf("\n");

	return 0;
}

■実行結果■

画像(ce_6_3)

ポインタ変数「p」に保存されたアドレス自体を変更する事によって値を確認したり、値を変更したりしております。

p++;

とインクリメントするとアドレスが一つずれるのが確認できますね!

もちろん

p += 2;

のように計算する事も配列の大きさを超えない範囲で可能です。

これを使えばより柔軟にいろんな場面に対応させる事ができますね!

ややこしい例

ポインタの持ってる内容、

たとえば先ほどのプログラムでいうトコロの

*p

こちらをインクリメントしたい時は

(*p)++

このように書きます。

*p++	

こうやって書いてしまうとアドレスを先にずらして内容を確認している事になってしまうので注意です。

こういうややこしい場合は計算を分けたり、()かっこをつけて計算の順番を守ったりしましょう。

気を付けて!

さきほどのプログラムで例えば、

*(p + 10) = 100;

とすれば先頭アドレスから10番目の場所が「100」になりますよね。

でもプログラム中では、5番目までは配列で宣言したけど、それ以上はしてません。

そこには

「ウインドウズがシステム管理の為に使っている超大事な数字」

があったりします。

なのでこの部分を大丈夫、大丈夫と好きかってにいじったりすると、データが破壊されたり、最悪PCが起動不能になったりもするので

ぜったいにやってはいけません!!!

まあ最近のコンパイラやPCなどはエラー対策をしていたりするそうですが、念のため!やめておきましょう!

ポインタ演算

今回やったアドレスの計算の事をポインタ演算っていいます。

これをやっていいのは足し算か引き算だけです。

かけ算やわり算は使ってはいけません。

では少し話が長くなってきたので続きは次回にしたいと思います!

次回

七日目 ポインタ4

□ページの先頭へ□

□目次へ戻る□

□HOME□

広告

↓2017年06月16日発売↓

やさしいC 第5版 (「やさしい」シリーズ)

新品価格
¥2,700から
(2017/5/1 13:05時点)

↓2014年08月09日発売↓

新・明解C言語 入門編 (明解シリーズ)

新品価格
¥2,484から
(2017/5/1 13:08時点)

↓2016年02月20日発売↓

新・解きながら学ぶC言語

新品価格
¥2,160から
(2017/5/1 13:10時点)

↓2017年02月11日発売↓

C言語プログラミング基本例題88 88

新品価格
¥3,024から
(2017/5/1 13:12時点)

↓2016年12月15日発売↓

Cの絵本 第2版 C言語が好きになる新しい9つの扉

新品価格
¥1,490から
(2017/5/1 13:13時点)

↓2017年02月08日発売↓

新・明解C言語で学ぶアルゴリズムとデータ構造 (明解シリーズ)

新品価格
¥2,700から
(2017/5/1 13:15時点)