第7講 ポインタ
第3話 謎の解明
コード再掲

#include<iostream> //入出力のために組み込む
using namespace std; //coutを使えるようにするために必要
void f(); //関数f()のプロトタイプ宣言
int main() {
  f(); //関数f()に仕事を命じている
  return(0);
}
void f() {
  int *b; //ポインタbの宣言
  *b = 1; //箱*bに1を入れる
  cout << "b =" << b << endl; //アドレスを入れる箱bの中身を表示
  cout << "*b=" << *b << endl; //箱bの中身=アドレスにある箱の中身の表示
}
001

ところが、Ctrl+F5で実行してみると、
001
とエラーしてしまいます。
エディタがコードの問題なしのお済み付けを与えても、
実行するとエラーしてしまうことはよくあります。
今回もその例となります。
何が問題でしょうか。
エラー原因を探るために、
前回のコードを
#include<iostream> //入出力のために組み込む
#include<iostream> //入出力のために組み込む
using namespace std; //coutを使えるようにするために必要
void f(); //関数f()のプロトタイプ宣言
int main() {
  f(); //関数f()に仕事を命じている
  return(0);
}
void f() {
  int a,*b; //ポインタbの宣言
  a = 1; //箱aに1を入れる
  b = &a; //住所を収納する箱bに箱aの住所を代入
  cout << "b   =" << b << endl; //アドレスを入れる箱bの中身を表示
  cout << "b + 1 =" << b + 1 << endl; //箱bの中身に1つ加えたものを表示
}
と書き換えてみましょう。
実行画面は、
011
の不思議な結果になりました。
b + 1とbに1加えただけですから、
b + 1 =010FFBA5
であるはずなのに、
b + 1 =010FFBA8
となっています。
実は、記憶装置の一定容量のメモリを割り振るといいましたが、
変数の方によって割り振る容量は変わってきます。
int型の場合4バイトが割り振られます。
(16進法でも繰り上がりが生じない範囲なら10進法と計算は同じです。
進法が変わると繰り上がりの仕方が変わるだけです。)

long long型なら8バイトです。
double型も同じ8バイトです。
(int型の箱aに割り振られたメモリは、
010FFBA4から010FFBA8です。
b = 010FFBA5
だから、010FFBA5から010FFBA8のはずだとお思いになりますよね。
実はメモリの割り振りが010FFBA5から010FFBA8のとき、
メモリアドレス(メモリ番地)は010FFBA4とするのがC言語やC++の文法なのです。
割り振られたメモリの1つ前の番地をメモリのアドレスとするという定義になっているのです。)

int型は4バイトですので、
b + 1は4増加の010FFBA8としてくれるようにC言語やC++は出来ているのです。
ですから、もし8バイトであれば、
b + 1は8増加にしてくれるのです。
これはC++のサービスなのです。

さて、
001
エラーの解消は
#include<iostream> //入出力のために組み込む
using namespace std; //coutを使えるようにするために必要
void f(); //関数f()のプロトタイプ宣言
int main() {
  f(); //関数f()に仕事を命じている
  return(0);
}
void f() {
  int *b =
(int *)malloc(sizeof(int)); //ポインタbの宣言
  *b = 1; //箱*bに1を入れる
  cout << "b =" << b << endl; //アドレスを入れる箱bの中身を表示
  cout << "*b=" << *b << endl; //箱bの中身=アドレスにある箱の中身の表示
}
でできます。
012
(int *)malloc(sizeof(int)); の部分はメモリサイズの定義と確保です。
sizeof(int)はintのサイズという意味で、4バイトです。
これによって、*bに4バイト分のメモリが確保されます。
#include<iostream> //入出力のために組み込む
using namespace std; //coutを使えるようにするために必要
void f(); //関数f()のプロトタイプ宣言
int main() {
  f(); //関数f()に仕事を命じている
  return(0);
}
void f() {
  int a, *b; //変数aとポインタbの宣言
  a = 1; //箱aに1を入れる
  b = &a; //住所を収納する箱bに箱aの住所を代入
  cout << "a  =" << a << endl; //箱aの中身を表示
  cout << "&a =" << &a << endl; //箱aの住所を表示
  cout << "b  =" << b << endl; //住所を収納する箱の中身を表示
  cout << "*b =" << *b << endl; //住所の箱に入っている中身を表示
}
において=(int *)malloc(sizeof(int)); が必要でなかったのは、
  b = &a; //住所を収納する箱bに箱aの住所を代入
という初期化(最初の代入)を通して、
*bのメモリサイズが4バイトであることがわかったからです。
というのはaのサイズが4バイトであったからです。
でもこちらが例外でポインタを定義するときには、
  int *b=(int *)malloc(sizeof(int)); //ポインタbの宣言と初期化
のように確保すべきメモリサイズをコンピュータに教えるのが正道です。
確保したメモリサイズが4バイトであるために、
#include<iostream> //入出力のために組み込む
#include<stdlib.h> //malloc()が使えるようにインクルード
using namespace std; //coutを使えるようにするために必要
void f(); //関数f()のプロトタイプ宣言
int main() {
  f(); //関数f()に仕事を命じている
  return(0);
}
void f() {
  int *b = (int *)malloc(sizeof(int)); //ポインタbの宣言
  *b = 1; //箱*bに1を入れる
  cout << "*b  =" << *b << endl; //箱bの中身=アドレスにある箱の中身の表示
  cout << "b   =" << b << endl; //アドレスを入れる箱bの中身を表示
  
cout << "b + 1 =" << b + 1 << endl; //箱*bの次の住所b+1表示
}
とすると、
013
となります。確保すべき容量が4バイトであることがわかったからです。
(16進法ですから
003B9478,003B9479,003B94A,003B947B,003B947C
であることにご注意!)

さて、皆さんコードを
#include<iostream> //入出力のために組み込む
using namespace std; //coutを使えるようにするために必要
void f(); //関数f()のプロトタイプ宣言
void g(); //関数g()のプロトタイプ宣言
int main() {
  f(); //関数f()に仕事を命じている
  g(); //関数g()に仕事を命じている
  return(0);
}
void f() {
  int a[10], i; //配列と制御変数の定義
  for (i = 0; i < 10; i++)a[i] = i + 1; //データ作成
  for (i = 0; i < 10; i++)cout << a[i] << " "; //データ表示
  cout << endl; //改行
}
void g() {
  int *a = (int *)malloc(sizeof(int) * 10), i; //配列と制御変数の定義
  for (i = 0; i < 10; i++)a[i] = i + 1; //データ作成
  for (i = 0; i < 10; i++)cout << a[i] << " "; //データ表示
  cout << endl; //改行
}
と変更して実行するとどうなると思いますか。


第2話へ   第4話へ

002

初心者のための excel 2016 マクロ VBA 入門講義 基礎から応用まで
vc++ c言語 c++ 入門 初心者 基礎から応用まで
eclipse c++ 入門
魔方陣 数独で学ぶ VBA 入門

数独のシンプルな解き方・簡単な解法の研究
VB講義へ
VB講義基礎へ
初心者のための世界で一番わかりやすいVisual C++入門基礎講座
初心者のための世界で一番わかりやすいVisual Basic入門基礎講座
初心者のための世界で一番わかりやすいVBA入門講義(基礎から応用まで)
初心者のための VC++による C言語 C++ 入門 基礎から応用まで第1部
eclipse java 入門
java 入門 サイト 基礎から応用まで
本サイトトップへ