ここではポインタ変数をつかってアドレスを格納するのではなく文字や数値データを格納する方法をまなんでみましょう。

1つのポインタ変数宣言をつかって複数の文字データや文字列データをコンピュータのメモリに簡単に1度に格納する方法はあるのですが複数の数値データを1度に簡単に格納する方法はないのです

ソーラー「だいぶん ポインタ変数について


理解がすすんだんじゃないかな。


もうおわっちゃうよ。


ここらへんで漫才といこうじゃ・・」


アレサ「はいっそうですね。


すこしだけ ちよっちよっと おさらいしてみますか?


まずは


ポインタ変数をつかって文字列データ"apple"をメモリに取り込む場合です。」


ソーラー「おねがいしま~す」


アレサ「


#include <stdio.h>

int main(void){


char *hairetu="apple";/*〇hairetuのポインタ変数宣言,初期化〇*/


printf("%s\n",hairetu);

printf("%c\n",hairetu[0]);

printf("%c\n",hairetu[1]);

printf("%c\n",hairetu[2]);

printf("%c\n",hairetu[3]);

printf("%c\n",hairetu[4]);

printf("%c\n",hairetu[5]);


return 0;

}


コンパイル結果

apple

a

p

p

l

e

(空白)

続行するには何かキーをおしてください


アレサ「


char *hairetu="apple";


/*🌞hairetuのポインタ変数宣言、初期化*/


が実行されると


自動的に


文字データを収める

char型の配列変数

hairetu[0]

hairetu[1]

hairetu[2]

hairetu[3]

hairetu[4]

hairetu[5]

が生成され


文字列データ"apple"は


char型の配列変数

hairetu[0]

hairetu[1]

hairetu[2]

hairetu[3]

hairetu[4]

hairetu[5]

hairetu[0]='a'

hairetu[1]='p'

hairetu[2]='p'

hairetu[3]='l'

hairetu[4]='e'

hairetu[5]='\0'

と取り込まれました。」


☆  ☆  ☆  


正確な表現は以下のようになります。


char *hairetu="apple";


/*🌞hairetuのポインタ変数宣言、初期化*/


が実行されると


文字列データ"apple"はメモリに格納されます。


そして[ ]演算子のエピソードでも見てきたように


ポインタ変数hairetuに[ ]演算子を用いた


hairetu[0]

hairetu[1]

hairetu[2]

hairetu[3]

hairetu[4]

hairetu[5]


を用いて


文字列データ"apple"を格納しているメモリに


アクセスすることができます。


char *hairetu="apple";


によって


作製されたポインタ変数hairetuには


文字列データ"apple"を格納している連続したメモリの先頭のメモリのア


ドレスが格納されています。


そして


文字列データ"apple"を格納している連続したメモリの先頭のメモリには


文字データ'a'が格納されています。


この状態で


[ ]演算子をポインタ変数hairetuにもちいれば


まず


hairetu[0]は文字データ'a'を


格納しているメモリにアクセスすることができるようになります


ポインタ変数hairetuに文字データ'a'を格納しているメモリのアドレスを代入すると


[ ]演算子をポインタ変数hairetuに用いた


hairetu[0]は


そのアドレス番号の付いたメモリに


格納されている文字データ'a'をあらわすようになるのです


hairetu[1]は


hairetu[0]がアクセスしているメモリの次のメモリに


アクセスします


hairetu[0]がアクセスしているメモリの次のメモリには


文字データ'b'


が格納されているので


hairetu[1]は


文字データ'b'を格納しているメモリにアクセスすることとなります。


そのようにして


配列変数

hairetu[0]

hairetu[1]

hairetu[2]

hairetu[3]

hairetu[4]

hairetu[5]



それぞれ


文字データ'a'

文字データ'b'

文字データ'c'

文字データ'd'

文字データ'e'

文字データ'\0'


を格納しているメモリにアクセスすることができます。


その結果


配列変数

hairetu[0]

hairetu[1]

hairetu[2]

hairetu[3]

hairetu[4]

hairetu[5]


'a'

'b'

'c'

'd'

'e'

'\0'

を表すようになり


hairetu[0]='a';

hairetu[1]='b';

hairetu[2]='c';

hairetu[3]='d';

hairetu[4]='e';

hairetu[5]='\0';


が実行されたようにみえます。



              solarplexussより

☆  ☆  ☆



ソーラー「そうだった そうだった


なつかしいな


そして文字列データ"apple"をメモリに格納する際は


ナル文字'\0'(空白)が


'a','p','p','l','e'につづいて


char型の配列変数

hairetu[5]に格納されるので


printf("%c\n",hairetu[5]);

が実行されると


コンパイル結果

apple

a

p

p

l

e

(空白)

続行するには何かキーをおしてください


のように


eのあとに空白が表示されるのだったね」


アレサ

「そして 文字列データ"apple"をメモリに取り込む場合と


ただ単に


文字データ'a','p','p','l','e'を1文字ずつメモリに取り込む場合との違い


が 


この'\0'を


'a','p','p','l','e'を1文字ずつメモリに取り込んだ


後に格納するということでした。


'\0'が格納されていることにより


コンピュータはappleをひとまとまりの文字列と認識し


printf("%s\n",hairetu);


を実行すると


appleがコマンドプロンプト画面に表示されるというわけです。」



ソーラー「ほんと、


この仕組みよくできているよね。」


アレサ


「では、ではですね。


次のプログラムでは


ポインタ変数hairetuをつかって


文字列データ"123"をメモリにとりこんでみましょう。


数値123ではありません。


文字列データ"123"です。


""ダブルクォーテーションで囲まれたデータは


中身が数値であっても文字列データをあらわすようになるのでしたね。


原理的には


ポインタ変数hairetuをつかって


文字列データ"apple"をメモリにとりこむときと全く同じです。」


#include <stdio.h>

int main(void){


char *hairetu="123";/*〇hairetuのポインタ変数宣言,初期化〇*/


printf("%s\n",hairetu);

printf("%c\n",hairetu[0]);

printf("%c\n",hairetu[1]);

printf("%c\n",hairetu[2]);

printf("%c\n",hairetu[3]);


return 0;

}


コンパイル結果


123

1

2

3

(空白)

続行するには何かキーを押して下さい_


アレサ「

このプログラムのように


char型のポインタ変数宣言、初期化


char *hairetu="123";


がおこなわれた場合 


char型の配列変数

hairetu[0]

hairetu[1]

hairetu[2]       

hairetu[3]


が生成されます。


そして

char型の配列変数

hairetu[0]

hairetu[1]

hairetu[2]

hairetu[3]



hairetu[0]='1'

hairetu[1]='2'

hairetu[2]='3'

hairetu[3]='\0'


文字データ

'1'

'2'

'3'

'\0'

が格納されていきます。


☆  ☆  ☆


正確には


"char型の配列変数

hairetu[0]

hairetu[1]

hairetu[2]

hairetu[3]

を用いて

文字データ

'1'

'2'

'3'

'\0'

格納されているメモリにアクセスすることができる"


です


☆  ☆  ☆



文字列データ"123"が


文字データ

'1'

'2'

'3'

'\0'

と分割されて


char型の配列変数

hairetu[0]

hairetu[1]

hairetu[2]

hairetu[3]

に格納されているわけです


char型の配列変数は-128から127までの数値データを格納することが


できますが


文字列データ"123"が


char型の配列変数

hairetu[0]に

hairetu[0]=123;

のように


格納されることはありません。


文字データ'1'、'2'、'3'、'\0'と分割されて


char型の配列変数

hairetu[0]

hairetu[1]

hairetu[2]

hairetu[3]

に格納されています。


そして


この文字データ'1'、'2'、'3'、'\0'は


シングルクォーテーションで囲われているので

char型の配列変数

hairetu[0]

hairetu[1]

hairetu[2]

hairetu[3]

として取り込まれており


数値データとしてとりこまれているわけではありませんですの。


プログラムをよく見ると


hairetu[0]

hairetu[1]

hairetu[2]

hairetu[3]

に格納された


文字データ


'1'、'2'、'3'、'\0'を

以下のようにprintf出力表示する際


printf("%s\n",hairetu);

printf("%c\n",hairetu[0]);

printf("%c\n",hairetu[1]);

printf("%c\n",hairetu[2]);

printf("%c\n",hairetu[3]);


このとき


数値をprintf出力表示する🐦%d出力変換指定子🐦でなく


文字をprintf出力表示する🐤%c出力変換指定子🐤がつかわれていますね。」







ソーラー「このプログラムのポインタ変数宣言、初期化


char *hairetu="123";


をみればわかるように


123はダブルクォーテーション""で囲まれているんだ


だから


123は数値でなく文字列データとして扱われるんだね。」



アレサ「ではではでは😊


char *hairetu[]={"1","2","3"};


とポインタ変数宣言をおこなった場合はどうでしょうか?



char *hairetuでなく


char *hairetu[]と記述されているのがポイントですの。



これらの文字データ"1","2","3"は


数値データとしてメモリに格納されるのでしょうか?


文字データとしてメモリに格納されるのでしょうか?


文字列データとしてメモリに格納されるのでしょうか?」



ソーラー「このポインタ変数宣言のタイプではでは😊


今さっきのポインタ変数宣言


char *hairetu="123";


とは ちょ~っとちがうんだった。


けど いっしょかな?


char *hairetu="123";


では

char型の配列変数

hairetu[0]

hairetu[1]

hairetu[2]


hairetu[0]='1'

hairetu[1]='2'

hairetu[2]='3'


と一文字ずつしか文字データを取り込めませんでした。


それが例えば


ポインタ変数宣言


char *hairetu[]={"abcdef","ghijkl","mnopqr"};


を行うと


先のエピソードでもみてきたように



     ポインタ変数💖💖💖💖💖💖である

hairetu[0]

hairetu[1]

hairetu[2]


char*hairetu[0]="abcdef";

char*hairetu[1]="ghijkl";

char*hairetu[2]="mnopqr";


が実行されているように


文字列データ


"abcdef"

"ghijkl"

"mnopqr"



メモリに格納できるんだったのさ(^_-)-☆


同じ


hairetu[0]

hairetu[1]

hairetu[2]


でも 1文字だけ文字データを取り込めるタイプと


文字列データを取り込めるタイプがあることになるんだね。


詳しく述べると


hairetu[0]='1'

hairetu[1]='2'

hairetu[2]='3'


と文字データを格納することになった


hairetu[0]

hairetu[1]

hairetu[2]




char*hairetu[0]="abcdef";

char*hairetu[1]="ghijkl";

char*hairetu[2]="mnopqr";

では


同じ


hairetu[0]

hairetu[1]

hairetu[2]

でも

hairetu[0]='1'

hairetu[1]='2'

hairetu[2]='3'

hairetu[0]

hairetu[1]

hairetu[2]

は文字データを格納する

の役割を


char*hairetu[0]="abcdef";

char*hairetu[1]="ghijkl";

char*hairetu[2]="mnopqr";

hairetu[0]

hairetu[1]

hairetu[2]

文字列データを格納する🍓ポインタ変数🍓の役割を果たしているんだね



char*hairetu[0]="abcdef";


はポインタ変数hairetu[0]を使って文字列データ"abcdef"を


メモリに格納していることになります。


しかし


char*hairetu[0]="abcdef";


は説明のための命令文であり


この命令文を実行することはできません。」



☆  ☆  ☆  ☆  ☆  ☆  ☆  ☆  ☆  ☆

このたとえ話の中では


hairetu[0]を1つのポインタ変数名とみなしているのですね。



              solarplexussより

☆  ☆  ☆  ☆  ☆  ☆  ☆  ☆  ☆  ☆


そのときポインタ変数hairetu[0]に[]演算子を用いると


配列変数

hairetu[0][0]

hairetu[0][1]

hairetu[0][2]

hairetu[0][3]

hairetu[0][4]

hairetu[0][5]

hairetu[0][6]

文字列データ"abcdef"を


格納しているメモリにアクセスして


hairetu[0][0]='a'

hairetu[0][1]='b'

hairetu[0][2]='c'

hairetu[0][3]='d'

hairetu[0][4]='e'

hairetu[0][5]='f'

hairetu[0][6]='\n'

をあらわすようになります。


このとき


文字データ'a'を格納しているメモリのアドレスを


格納しているポインタ変数は


           🍋hairetu[0]🍋


になるんだね。」



☆  ☆  ☆  ☆  ☆  ☆  ☆  ☆  ☆  ☆

補足


このことは


char*hairetu="abcdef";


を実行して


生成される配列変数

hairetu[0]

hairetu[1]

hairetu[2]

hairetu[3]

hairetu[4]

hairetu[5]

hairetu[6]


hairetu[0]='a';

hairetu[1]='b';

hairetu[2]='c';

hairetu[3]='d';

hairetu[4]='e';

hairetu[5]='f';

hairetu[6]='\n';



文字データが格納されたとき


文字データ'a'を格納しているメモリのアドレスを格納している


ポインタ変数はhairetuになるのに似ていますね。


hairetuの部分がhairetu[0]になっているというわけです。



                 solarplexussより

☆  ☆  ☆  ☆  ☆  ☆  ☆  ☆  ☆  ☆


ソーラー「


そして


char*hairetu[0]="abcdef";



char hairetu[0][]="abcdef";



仕組みが良く似ていて


どちらの場合でも


配列変数

hairetu[0][0]

hairetu[0][1]

hairetu[0][2]

hairetu[0][3]

hairetu[0][4]

hairetu[0][5]

hairetu[0][5]



hairetu[0][0]='a'

hairetu[0][1]='b'

hairetu[0][2]='c'

hairetu[0][3]='d'

hairetu[0][4]='e'

hairetu[0][5]='f'

hairetu[0][5]='\n'


をあらわすことになるんだ。」


☆  ☆  ☆  ☆  ☆  ☆  ☆  ☆  ☆  ☆

上記の仕組みも


char*hairetu="abcdef";



char hairetu[]="abcdef";



仕組みが良く似ていて


どちらの場合でも


hairetu[0]='a'

hairetu[1]='b'

hairetu[2]='c'

hairetu[3]='d'

hairetu[4]='e'

hairetu[5]='f'

hairetu[6]='\n'


をあらわすことになるのに似ています。


                 solarplexussより

☆  ☆  ☆  ☆  ☆  ☆  ☆  ☆  ☆  ☆




アレサ


「そうですね。ソーラーさん


次のプログラムをご覧ください」


#include <stdio.h>

int main(void){


char *hairetu[]={"abcdef","ghijkl","mnopqr"};


printf("%s\n",hairetu[0]);

printf("%s\n",hairetu[1]);

printf("%s\n",hairetu[2]);

return 0;

}


コンパイル結果


abcdef

ghijkl

mnopqr



アレサ「

文字列データ"abcdef"が

hairetu[0][0]のアドレスを格納しているポインタ変数hairetu[0]を使ってprintf出力表示されています。

文字列データ"ghijkl"が

hairetu[1][0]のアドレスを格納しているポインタ変数hairetu[1]を使ってprintf出力表示されています。

文字列データ"mnopqr"が

hairetu[2][0]のアドレスを格納しているポインタ変数hairetu[2]を使ってprintf出力表示されています。


アレサ「


まるで

配列

hairetu[0]

hairetu[1]

hairetu[2]


それぞれ

文字データ

"abcdef"

"ghijkl"

"mnopqr"

が格納されているようですね。


実際には


ポインタ変数

hairetu[0]

hairetu[1]

hairetu[2]

文字データ

"abcdef"

"ghijkl"

"mnopqr"

を格納しているメモリの先頭のメモリのアドレスを格納しています。



ポインタ変数

hairetu[0]

hairetu[1]

hairetu[2]


を使って


メモリに格納されている

文字列データ

"abcdef" 

"ghijkl"

"mnopqr"


表示するには

printf("%s\n",hairetu[0]);

printf("%s\n",hairetu[1]);

printf("%s\n",hairetu[2]);


と記述します。」



☆  ☆  ☆  ☆  ☆  ☆  ☆  ☆  ☆  ☆


配列hairetuを用いて


char hairetu[]="abcdef";


を実行したとき


hairetu[0]='a'

hairetu[1]='b'

hairetu[2]='c'

hairetu[3]='d'

hairetu[4]='e'

hairetu[5]='f'

hairetu[6]='\n'


と文字データが格納されますが


そのとき


文字列abcdefをコマンドプロンプト画面に表示するには


文字列データ"abcdef"を格納している先頭のメモリのアドレスを

格納している


ポインタ変数


hairetuを使って


printf("%s\n",hairetu);


と記述します。


printf("%s\n",hairetu[0]);

printf("%s\n",hairetu[1]);

printf("%s\n",hairetu[2]);


と記述するのも原理は全く同じです。


                solarplexussより

☆  ☆  ☆  ☆  ☆  ☆  ☆  ☆  ☆  ☆


アレサ「


このように


文字列データ


"abcdef" 

"ghijkl"

"mnopqr"



%s出力変換指定子をつかってprintf出力表示する場合は


printf関数の第2引数には

文字列データ"abcdef"を格納している先頭のメモリのアドレスを

格納しているポインタ変数hairetu[0]

文字列データ"ghijkl"を格納している先頭のメモリのアドレスを

格納しているポインタ変数hairetu[1]

文字列データ"mnopqr"を格納している先頭のメモリのアドレスを

格納しているポインタ変数hairetu[2]


を記述します。」


ソーラー「なるほど


%s出力変換指定子をつかって


ポインタ変数の格納しているアドレスのメモリの


格納している


文字データを先頭とした


文字列データを


コマンドプロンプト画面に出力表示する


printf("%s\n",hairetu[0]);

printf("%s\n",hairetu[1]);

printf("%s\n",hairetu[2]);


この表記方法は


よくみかけるね😊」


アレサ「


それではお待たせいたしました。


ポインタ変数宣言

char *hairetu[]={"1","2","3"};


の仕組みをみていきたいのです。


これらの文字列データ"1","2","3"は


数値データとしてメモリに格納されるのでしょうか?


文字データとしてメモリに格納されるのでしょうか?


文字列データとしてメモリに格納されるのでしょうか?」


ソーラー「文字列データ"1","2","3"は・・・


たのむよ~~~😊アレサちゃ~ん」


アレサ


「次のプログラムをご覧ください」


#include <stdio.h>

int main(void){


char *hairetu[]={"1","2","3"};


printf("%s\n",hairetu[0]);

printf("%s\n",hairetu[1]);

printf("%s\n",hairetu[2]);

return 0;

}


コンパイル結果

1

2

3



アレサ「

ここで

hairetu[0]

hairetu[1]

hairetu[2]

ポインタ変数となっています。




さきほどのポインタ変数宣言


char *hairetu="123";

によって作製された


char型の配列変数

hairetu[0]

hairetu[1]

hairetu[2]


hairetu[0]='1';

hairetu[1]='2';

hairetu[2]='3';


と文字データをとりこんだときの


char型の配列変数

hairetu[0]

hairetu[1]

hairetu[2]


とは


違い

hairetu[0]

hairetu[1]

hairetu[2]


ポインタ変数なのです。



char *hairetu="123";


では


char型の配列変数

hairetu[0]

hairetu[1]

hairetu[2]


hairetu[0]='1';

hairetu[1]='2';

hairetu[2]='3';


文字データ'1'、'2'、'3'を格納していました。


それに対し


char *hairetu[]={"1","2","3"};


が実行されると


あたかも


char *hairetu[0]="1";

char *hairetu[1]="2";

char *hairetu[2]="3";


が実行されているようになります。


つまり


ポインタ変数


hairetu[0]

hairetu[1]

hairetu[2]


を使って


"1"、"2"、"3"をメモリに格納しています。


その際

ポインタ変数


hairetu[0]

hairetu[1]

hairetu[2]

に[]演算子を用いた


hairetu[0][0]

hairetu[0][1]

hairetu[1][0]

hairetu[1][1]

hairetu[2][0]

hairetu[2][1]

hairetu[0][0]='1'

hairetu[0][1]='\0'

hairetu[1][0]='2'

hairetu[1][1]='\0'

hairetu[2][0]='3'

hairetu[2][1]='\0'


をあらわすことになります。




そして



文字列データ"1"、"2"、"3"をprintf出力表示する際


printf("%s\n",hairetu[0]);

printf("%s\n",hairetu[1]);

printf("%s\n",hairetu[2]);


printf関数の第1引数には


文字列データをprintf出力表示する


%s出力変換指定子が



printf関数の第2引数には


文字列データ"1"、"2"、"3"を格納しているメモリの中の


先頭のメモリのアドレスを格納しているポインタ変数


hairetu[0]

hairetu[1]

hairetu[2]

用いられています。



🍋  🍋  🍋  🍋  🍋  🍋  🍋


よく観察すると


まるで

配列名が

hairetu[0]

hairetu[1]

hairetu[2]

の配列に

文字列データ

"1"

"2"

"3"

hairetu[0][0]='1';

hairetu[0][1]='\0';

hairetu[1][0]='2';

hairetu[1][1]='\0';

hairetu[2][0]='3';

hairetu[2][1]='\0';



格納されているようにもみえます。


コンパイル結果

1

2

3

だけ見ると

コンピュータのメモリに


数値1,2,3がとりこまれているようにみえますが


このポインタ変数宣言


char *hairetu[]={"1","2","3"};

が行われた場合は


文字列データ"1"、"2"、"3"🍎🍎🍎🍎🍎🍎


メモリに格納しており


数値データ

1

2

3

がメモリに

とりこまれているわけではないのです。


               solarplexussより


🍋  🍋  🍋  🍋  🍋  🍋  🍋



ソーラー「文字列データを


1度のポインタ変数宣言で簡単にとりこむ方法は


文字列データが1つなら

char *hairetu="123";


文字列データが複数なら

char *hairetu[]={"abcdef","ghijkl","mnopqr"};



これできまり!


だね。」


アレサ

「はいっ


以上のように


ポインタ変数を使って文字列データを1度に


コンピュータのメモリに格納する便利な方法には


1つの文字列データ"123"を取り込む場合には


char *hairetu="123";



複数の文字列データ

"1","2","3"や

"123","456","789","102020”,”882288”


を取り込む場合には


char *hairetu[]={"1","2","3"};


char *hairetu[]={"123","456","789","102020","882288"};


の格納パターン


この2つがあるのですね。」



ソーラー「それでは


1度のポインタ変数宣言で


文字列データ"1","2","3"でなく


数値データの1,2,3を😋簡単に😋格納するにはどうしたらいいんだったけか?」


アレサ「それは・・・」


ソーラー「それは・・・」


アレサ「全く・・・」


ソーラー「そういえば それ、やってなかったっけ?」


アレサ「はいっ 全く・・・」


ソーラー「ま、まあ、いっか


次、次 いってみよ」


アレサ「

では~~


char *hairetu[]のような


ポインタ変数宣言をおこない

生成される

ポインタ変数

hairetu[0]

hairetu[1]

hairetu[2]

を用いて

            『1度に』

            『簡単に』

            

数値データ

1

2

3

をメモリにとりこむことはできるのでしょうか?」


ソーラー「ええっとぉ~???


ア、アレサさあ~ん


なんかできそうな感じは・・するけど・・・」



アレサ「ではまず


手始めに


次のようにプログラムを構成し


#include <stdio.h>

int main(void){


int *hairetu={1,2,3};


printf("%s\n",hairetu[0]);

printf("%s\n",hairetu[1]);

printf("%s\n",hairetu[2]);

return 0;

}


1度に簡単に数値データ

1

2

3

hairetu[0]=1;

hairetu[1]=2;

hairetu[2]=3;

のように

メモリに格納できるか試してみますの


☆  ☆  ☆  ☆  ☆  ☆  ☆  ☆  ☆

int *hairetu={1,2,3};

(🌞このようなポインタ変数宣言、初期化が実行できるかどうかということですね🌞)


                solarplexussより

☆  ☆  ☆  ☆  ☆  ☆  ☆  ☆  ☆


int *hairetu={1,2,3};

が実行されて


配列変数

hairetu[0]

hairetu[1]

hairetu[2]

が生成されて


hairetu[0]=1;

hairetu[1]=2;

hairetu[2]=3;

のようにデータが

格納できれば良いのですが・・・」


ソーラー「それではコンパイルしてみようよ アレサ」


アレサ「はい😊 コンパイル」


#include <stdio.h>

int main(void){


int *hairetu={1,2,3};


printf("%s\n",hairetu[0]);

printf("%s\n",hairetu[1]);

printf("%s\n",hairetu[2]);

return 0;

}


コンパイル結果


EAZY IDECの場合


ファイル「C:/Users/solarplexuss/AppData/Local/EasyIDEC/project/hhhhhhhh/main.c」の

「4行目」で記述エラーを発見しました。

警告

assignment makes pointer from integer without a cast

ファイル「C:/Users/solarplexuss/AppData/Local/EasyIDEC/project/hhhhhhhh/main.c」の

「4行目」で記述エラーを発見しました。

「}」を付け忘れています。


Visual Studioの場合


エラー (アクティブ) E0146 初期化子の値が多すぎます

エラー C4700 初期化されていないローカル変数 'hairetu' が使用されます


アレサ「ソーラーさん 


int *hairetu={1,2,3};


のような


ポインタ変数宣言、初期化は実行できないようですの」


ソーラー「あれ?なんかできそうな感じなんだけどなあ~?」



アレサ「ポインタ変数宣言をおこない


数値を1つだけ


たとえば


数値1だけをメモリにとりこむなら


1つの変数宣言


int a=1;


をおこない


その変数aのアドレスを格納するために


1つのポインタ変数宣言


int *hairetu;


を行い→

😊  😊  😊  😊  😊  😊  😊  😊


このように

int *hairetu;


をおこなったなら


ポインタ変数hairetuに[]演算子を用いた


配列変数

hairetu[0]

hairetu[1]

hairetu[2]

をつかって


メモリに格納されているデータに


アクセスすることができるようになります


たとえば


char *hairetu="abc";


のようにポインタ変数が🍓初期化🍓されると


ポインタ変数hairetuに[]演算子を用いた


配列変数

hairetu[0]

hairetu[1]

hairetu[2]

hairetu[3]

をもちいて

文字データ

'a'

'b'

'c'

を格納しているメモリにアクセスし


配列変数

hairetu[0]

hairetu[1]

hairetu[2]

hairetu[3]


hairetu[0]='a'

hairetu[1]='b'

hairetu[2]='c'

hairetu[3]='\0'


を表すようにすることができます。


別の言い方をするなら


char *hairetu="abc";


が実行されると


配列変数

hairetu[0]

hairetu[1]

hairetu[2]

hairetu[3]

が生成されて

hairetu[0]='a';

hairetu[1]='b';

hairetu[2]='c';

hairetu[3]='\0';


が実行されているともいえます。


😊  😊  😊  😊  😊  😊  😊  😊


アレサ「

作製された


ポインタ変数hairetuに変数aのアドレス&aを代入し


変数aのアドレス&aのメモリにアクセスすることができるようになった


*hairetuを用いて


*hairetuに1を格納するという方法があります。


数値1だけをメモリにとりこむだけなら


ポインタ変数宣言


int *hairetu;


を行って


できないことはありません。


そのときのプログラムは次のようになります。」


#include <stdio.h>


int main(void){

int a;

a=1;

int *hairetu;

hairetu=&a;

printf("%d\n",*hairetu);

return 0;

}


コンパイル結果

1


アレサ「ただ、このプログラムはとっても面白いことが


行われたことになるのです


みなさん


それがわかるかな~~~?」



ソーラー「??プログラムは正確にかけてるようだけど・・・


おもしろいことねえ。


それって僕のギャグが面白いってこと?かな?


ほめてもらえたのかな?」


solarplexuss「 面白いこと?


ポインタ変数hairetuに


数値データ1を格納している変数aのアドレス&aを格納したから


[ ]演算子をポインタ変数hairetuに用いた


hairetu[0]


はアドレス&aの番号の付いたメモリにアクセスして


数値データ1をあらわすようになった


ことかな?


フフフ」



アレサ「このプログラムは


ポインタ変数宣言を行って


数値1をコンピュータのメモリに格納するためにつくられました。


そして


メモリに格納された


数値1をコマンドプロンプト画面にprintf出力表示しました。


このプログラムが実行された後は


メモリの節約のため


コンピュータのメモリに格納されていた数値1は消去されています」


ソーラー「うん、うん、そのとおり😊」


アレサ 「ポインタ変数宣言をおこない


数値1を


メモリに格納したいのでしたね」


ソーラー「そうさ😊」


アレサ

「ソーラーさん


int a;

a=1;

int * hairetu;

hairetu=&a;


ここに秘密がかくれているんですの」



ソーラー

「🐈

int a;

a=1;

int *hairetu;🐈

🐈 hairetu=&a;


どこかにゃ~ん」



アレサ

「ポインタ変数宣言を行い数値1を


メモリに格納したい


そのために


int a;

🐈にゃお~ん

a=1;

がおこなわれています。」


ソーラー「にゃにゃ😺」


アレサ「つまり


int a;

🐈にゃおにゃお~ん

a=1;

が行われた時点で


コンピュータのメモリに


数値1は格納されているんです


ポインタ変数宣言


int *hairetu;


をおこなうことにより


数値1をメモリに格納したのではなくて


ポインタ変数宣言をおこない


数値1を格納する*hairetuを作製しなくとも


すでに


変数aのアドレスに数値1が格納されているのです。」



ソーラー「はっ!!!!!!!!!」



アレサ「はい、それではソーラーさん いつものお言葉の時間です」



ソーラー 「なに、なあぁにぃぃぃぃぃぃぃ~~~~~~~ぃぃぃぃ


ぃぃぃぃぃ~~~~~~~


やっちまったなあああぁぁぁぁぁぁぁあああああああ」



🐤...


アレサ「そこで


このプログラムを


次のように変形します


#include <stdio.h>


int main(void){

int a;

int *hairetu;

hairetu=&a;


*hairetu=1;


/*変数aのアドレス&aの番号をもつメモリに


*hairetuを


つかって数値1を格納します*/


printf("%d\n",*hairetu);

return 0;

}


(EAZY IDECの場合)

(Visual Studioの場合)



コンパイル結果

1


これで

ポインタ変数宣言を行い


作製された*hairetuを使って数値1をメモリに格納できました」




ソーラー「おおおゅ・・・・


む、娘やぁぁぁぁあ・・・・


ナイスじゃないかぁぁぁぁぁあああんんん」


ソーラー「ところで


ポインタ変数宣言を行わず


ここで


🍅配列宣言🍅int hairetu[]={1,2,3};


をおこなえば


次のプログラムのように


あっさりと


#include <stdio.h>

int main(void){


int hairetu[]={1,2,3};

printf("%d\n",hairetu[0]);

printf("%d\n",hairetu[1]);

printf("%d\n",hairetu[2]);

return 0;

}


コンパイル結果

1

2

3


数値1,2,3を1度に


配列に格納することができたんだよねぇ~。


どうしたものかな」


アレサ「そうなんですの」


ソーラー「う~ん、いろいろ試したけど


1つの配列宣言

int hairetu[]={1,2,3};


を行ったら


1

2

3

の3つの複数の数値が1度に

配列に

hairetu[0]=1;

hairetu[1]=2;

hairetu[2]=3;


と格納されるように


1つのポインタ変数宣言をつかって


1

2

3

の3つの複数の数値を


メモリに1度にとりこむことはできないんだ~


先程は

int *hairetu={1,2,3};


を実行してみたけど


今度は


ためしに


配列宣言、初期化


int hairetu[]={1,2,3};


を真似て


ポインタ変数宣言、初期化


int *hairetu[]={1,2,3};


をおこなって


プログラムを構成、実行したとしても→」


#include <stdio.h>

int main(void){


int *hairetu[]={1,2,3};/*ここの部分ですね*/

printf("%d\n",hairetu[0]);

printf("%d\n",hairetu[1]);

printf("%d\n",hairetu[2]);

return 0;

}


コンパイル結果は


EAZY IDECの場合


ファイル「C:/Users/solarplexuss/AppData/Local/EasyIDEC/project/hhhhhhhh/main.c」の

「4行目」で記述エラーを発見しました。

警告

assignment makes pointer from integer without a cast

ファイル「C:/Users/solarplexuss/AppData/Local/EasyIDEC/project/hhhhhhhh/main.c」の

「4行目」で記述エラーを発見しました。

警告

assignment makes pointer from integer without a cast

ファイル「C:/Users/solarplexuss/AppData/Local/EasyIDEC/project/hhhhhhhh/main.c」の

「4行目」で記述エラーを発見しました。

警告

assignment makes pointer from integer without a cast



Visual Studioの場合

エラー (アクティブ) E0146 初期化子の値が多すぎます

エラー C2440 '初期化中': 'initializer list' から 'int *' に変換できません。



ソーラー「→


コンパイルエラーが表示されます。


つまり

コンピュータは

ポインタ変数宣言

int *hairetu[]={1,2,3};


int *hairetu[]を

int *aのような

ふつうのポインタ変数宣言と認識しており


つまり

hairetu[]を1つのポインタ変数のポインタ変数名とみなしており


int *hairetu[]によって作製されるポインタ変数


hairetu[]を


1

2

3

の3つの数値を用いて初期化できないと

エラー表示をだしています。


このとき

ポインタ変数

hairetu[0]

hairetu[1]

hairetu[2]

のようなものは作製されていません


また

int *hairetu[]

により

ポインタ変数

hairetu[0]

hairetu[1]

hairetu[2]

が作製されたとしても


ポインタ変数

hairetu[0]

hairetu[1]

hairetu[2]

配列変数

hairetu[0]

hairetu[1]

hairetu[2]

ではないので


hairetu[0]=1;

hairetu[1]=2;

hairetu[2]=3;


のように数値1,2,3をとりこむことはできないんじゃないかな?


さらに


今のこのプログラム👇の


#include <stdio.h>

int main(void){


int *hairetu[]={1,2,3};

printf("%d\n",hairetu[0]);/*ここの部分ですね*/

printf("%d\n",hairetu[1]);/*ここの部分ですね*/

printf("%d\n",hairetu[2]);/*ここの部分ですね*/

return 0;

}


%d出力変換指定子を


文字列を出力する%s出力変換指定子におきかえて


次のようにプログラムを書き換えても→」


#include <stdio.h>

int main(void){


int *hairetu[]={1,2,3};

printf("%s\n",hairetu[0]);/*ここの部分ですね*/

printf("%s\n",hairetu[1]);/*ここの部分ですね*/

printf("%s\n",hairetu[2]);/*ここの部分ですね*/

return 0;

}

コンパイル結果


EAZY IDECの場合


ファイル「C:/Users/solarplexuss/AppData/Local/EasyIDEC/project/hhhhhhhh/main.c」の

「4行目」で記述エラーを発見しました。

警告

assignment makes pointer from integer without a cast

ファイル「C:/Users/solarplexuss/AppData/Local/EasyIDEC/project/hhhhhhhh/main.c」の

「4行目」で記述エラーを発見しました。

警告

assignment makes pointer from integer without a cast

ファイル「C:/Users/solarplexuss/AppData/Local/EasyIDEC/project/hhhhhhhh/main.c」の

「4行目」で記述エラーを発見しました。

警告

assignment makes pointer from integer without a cast


Visual Studioの場合

エラー (アクティブ) E0144 型 "int" の値を使用して型 "int *" のエンティティを初期化することはできません

エラー (アクティブ) E0144 型 "int" の値を使用して型 "int *" のエンティティを初期化することはできません

エラー (アクティブ) E0144 型 "int" の値を使用して型 "int *" のエンティティを初期化することはできません

エラー C2440 '初期化中': 'int' から 'int *' に変換できません。

警告 C4477 'printf' : 書式文字列 '%s' には、型 'char *' の引数が必要ですが、可変個引数 1 は型 'int *' です

警告 C4477 'printf' : 書式文字列 '%s' には、型 'char *' の引数が必要ですが、可変個引数 1 は型 'int *' です

警告 C4477 'printf' : 書式文字列 '%s' には、型 'char *' の引数が必要ですが、可変個引数 1 は型 'int *' です


ソーラー「→


とエラー表示がでてきます。


う~ん


hairetu[0]

hairetu[1]

hairetu[2]

はポインタ変数となるので


%d出力変換指定子を

%s出力変換指定子に変更してみたのですが


うまくコンパイルできないね。



では


ど~しても💖


数値を


ポインタ変数宣言をつかってたくさん取り込みたい方は・・・


どうしたらいいのかということになるよね?よね?


そうだね・・・


手間はかかるけど


取り込みたい数だけ


変数宣言とポインタ変数宣言をおこなえば


いいんじゃないかな。」


アレサ「プログラムをつくってみます・・か😊・・


次のプログラムでは


3つの数値1,2,3を


3つの変数宣言と


3つのポインタ変数宣言をつかってメモリにとりこんでいますの。」


#include <stdio.h>


int main(void){

int a;

int b;

int c;


int *pta;

int *ptb;

int *ptc;


pta=&a;

ptb=&b;

ptc=&c;


*pta=1;

*ptb=2;

*ptc=3;


printf("%d\n",*pta);

printf("%d\n",*ptb);

printf("%d\n",*ptc);

return 0;

}

コンパイル結果


(EAZY IDECの場合)

(Visual Studioの場合)


1

2

3


アレサ「このプログラムでは


pta

ptb

ptc


ポインタ変数宣言


int *pta;

int *ptb;

int *ptc;

をおこなっています


このように🐤int型🐤のポインタ変数宣言


int *pta;

int *ptb;

int *ptc;


が行われた場合 


ポインタ変数

pta

ptb

ptc


    🐤整数値🐤を格納している変数のアドレスを


格納することになります。


ポインタ変数

pta

ptb

ptc


整数値を格納するint型の変数a,b,cの

アドレス

&a

&b

&c

pta=&a;

ptb=&b;

ptc=&c;

のように

格納されると


*pta

*ptb

*ptc


int型の変数aのアドレス&a

int型の変数bのアドレス&b

int型の変数cのアドレス&c


のメモリに格納されている数値をあらわします


そして


*pta

*ptb

*ptc



1

2

3

*pta=1;

*ptb=2;

*ptc=3;

と代入すると


int型の変数aのアドレスのメモリに数値1を

int型の変数bのアドレスのメモリに数値2を

int型の変数cのアドレスのメモリに数値3を


格納することができます。


このように


1つのポインタ変数宣言では


数値1,2,3を


メモリに格納することはできませんでしたが


3つのポインタ変数宣言を行えば


数値1,2,3を


コンピュータのメモリに


格納することができますね。


でも1度に簡単ではありませんの・・・」


ソーラー「ここは


ポインタ変数宣言の面白いところだね。


ポインタ変数宣言をつかって


一番基本的であるだろう


数値1,2,3を


1つのポインタ変数宣言を


int *hairetu={1,2,3};


のように記述して


同時に


コンピュータのメモリに格納する方法をC言語の開発者はつくらなかったんだ。


((^_^)/以下のプログラムは実行できません)


#include <stdio.h>

int main(void) {


int *hairetu={1,2,3};


printf("%d\n", hairetu[0]);

printf("%d\n", hairetu[1]);

printf("%d\n", hairetu[2]);

return 0;

}


なんでかな?」




このエピソードはまだまだ続きます😊

  • Twitterで共有
  • Facebookで共有
  • はてなブックマークでブックマーク

作者を応援しよう!

ハートをクリックで、簡単に応援の気持ちを伝えられます。(ログインが必要です)

応援したユーザー

応援すると応援コメントも書けます