文字列を格納するchar hairetu[ ]="nekoneko";とchar *hairetu="nekoneko";この2つを比較することによりポインタ変数の仕組みがより理解できるようになります

配列の代わりにポインタ変数をつかって文字列データをメモリに格納してみます 

お知らせ


うふっ


Visual Studio2019から


ポインタ変数を使って文字列データをメモリに格納する機能は削除されました


ですので


Visual Studio2019では


文字列データ"neko"を


ポインタ変数を使って

コンピュータのメモリに格納する


char* hairetu="neko";


を実行することはできなくなりました


Visual Studio2018以前のヴァージョンでは可能です


🌞  🌞  🌞  🌞  🌞  🌞


このエピソードは


文字列データ"neko"を


配列を使って

コンピュータのメモリに格納する


char hairetu[]="neko";


文字列データ"neko"を


ポインタ変数を使って

コンピュータのメモリに格納する


char* hairetu="neko";


では何がちがうのでしょうか?


のエピソードの導入部分になっています


お話はそちらのエピソードへ続いていきますので


そちらのエピソードも参考になさってください


より詳しく解説がなされています。


配列とポインタ変数の仕組みがより理解できるようになっています。


🌞  🌞  🌞  🌞  🌞  🌞


アレサ 「今までは文字列データを


次のように


配列宣言、初期化


char hairetu[100]="cgenngotanosii";


char hairetu[100]="nekonekofunnjyatta";


を実行し


配列hairetuに文字列データ


"cgenngotanosii"や


"nekonekofunnjyatta"


等をとりこんできました。


これ自体は、とても簡単なことでした。」


ソーラー「アレサ、もう、もう 配列の話とまらないんだね。」


アレサ「!(^^)!まだまだ配列の話、配列しつづけます。


配列hairetuをつかって


char hairetu[]="nekoneko";


と文字列データ"nekoneko"をメモリに格納できたように


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


char* hairetu="nekoneko";


と記述し


文字列データ"nekoneko"をメモリに格納することができます🍊



ソーラー「な、なんだ 


なんで??


ポインタ変数はアドレスを格納する変数だった気がするけど・・


char* hairetu="nekoneko";



のように



ポインタ変数hairetuに文字列データ"nekoneko"を代入なんてできるの?


わあおおうぅぅ なんて新しい考え方なんだ💦💦💦」


(🌞実はポインタ変数hairetuには文字列データが代入されているのではなく


文字列データ"nekoneko"を格納しているメモリの先頭のメモリのアドレスが代入されています


このことはいたるところで登場することになる重要なポイントなのです🌞)


アレサ「はいっ


char* hairetu="nekoneko";


と記述すると


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


ポインタ変数hairetuには


文字列データ"nekoneko"ではなく


文字列データ"nekoneko"を格納した連続したメモリの先頭のメモリのアドレスが


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


これからご紹介していくことになるのですが


ポインタ変数宣言


char* hairetu="nekoneko";


を実行して


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


文字列データ"nekoneko"により初期化をおこない


文字列データ"nekoneko"をメモリに格納することは


とても💖💖💖愛らしく簡単なのです。


それでは


実際にプログラムを構成し


配列hairetuに代わり


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


文字列データ"nekoneko"をメモリに格納していきます。


配列hairetuをつかった命令文


char hairetu[]="nekoneko";


の代わりに


ポインタ変数hairetuをつかった命令文


char* hairetu="nekoneko";


を使うことによって


文字列データ"nekoneko"をメモリに格納することとなります。


配列をつかって文字列データを格納する方法である


char hairetu[]="nekoneko";

ポインタ変数hairetuつかって文字列データを格納する方法である


char* hairetu="nekoneko";


は外見がとても良く似ています。


が違いがありますの。


それでは


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


文字列データ"nekoneko"をメモリに格納したあと


printf関数を使って文字列データ"nekoneko"を


コマンドプロンプト画面にprintf出力表示してみましょう。


そのプログラムは

以下のようになります

👇


#include <stdio.h>

int main(void){


char* hairetu="nekoneko";

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

printf(hairetu);

return 0;

}


コンパイル結果

(EAZY IDECの場合)

(Visual Studioの場合)


nekoneko

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


とコマンドプロンプト画面に表示されます。


今まで


配列hairetuを使ってメモリに格納された文字列データを


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


printf("%s",hairetu);

printf(hairetu);


の2つの表示方法を使っていました


同様に

ポインタ変数hairetuをつかってメモリに格納された文字列データを


コマンドプロンプト画面に表示するのにも


printf("%s",hairetu);

printf(hairetu);


の2つの表示方法を使うことができます。


今のプログラムでは その両方をつかって


文字列

nekoneko

nekoneko

を2つ表示してみました」


ソーラー 「ここで 気が付いたのが


printf(hairetu);



printf(hairetu\n);


と記述すると


EAZY IDECの場合


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

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

「\」の使い方が間違っています。\ を文字列の外で使っていないかどうか確認してください。



Visual Studioの場合


エラー (アクティブ) E0007 認識されないトークンです

エラー C2146 構文エラー: ';' が、識別子 'n' の前に必要です。

エラー C2146 構文エラー: ')' が、識別子 'n' の前に必要です。

エラー C2059 構文エラー: ')'

エラー C2017 エスケープシーケンスの使い方が正しくありません。

エラー C2065 'n': 定義されていない識別子です。



とエラーが出る所です


このためプログラムを実行することができません。


だから

printf(hairetu\n);

ではなく

printf(hairetu);

と記述するしかなく 改行できないため


コンパイル結果が


nekoneko

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


となっています。

(👆

nekoneko

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


がくっついています


くっつかない方法は

このエピソードの最後の方でご紹介していますので

参考になさってください)」


アレサ「


実は😊


ポインタ変数をつかって文字列データをメモリにとりこむとき


面白い仕組みがかくされているのですの


ポインタ変数をつかって文字列データをメモリにとりこむため


char* hairetu="nekoneko";



hairetuのポインタ変数宣言、初期化した時点で


配列宣言

char hairetu[100]="nekoneko";


をおこなったときと同じように


文字データを格納するchar型の配列変数

hairetu[0]

hairetu[1]

hairetu[2]

hairetu[3]

hairetu[4]

hairetu[5]

hairetu[6]

hairetu[7]

hairetu[8]


が生成されて


文字列データ”nekoneko”は


次のように


hairetu[0]='n'

hairetu[1]='e'

hairetu[2]='k'

hairetu[3]='o'

hairetu[4]='n'

hairetu[5]='e'

hairetu[6]='k'

hairetu[7]='o'

hairetu[8]='\0'


と格納されています。


これは配列宣言


char hairetu[100]="nekoneko";

を行い


生成された配列変数


hairetu[0]

hairetu[1]

hairetu[2]

hairetu[3]

hairetu[4]

hairetu[5]

hairetu[6]

hairetu[7]

hairetu[8]

文字データを


hairetu[0]='n'

hairetu[1]='e'

hairetu[2]='k'

hairetu[3]='o'

hairetu[4]='n'

hairetu[5]='e'

hairetu[6]='k'

hairetu[7]='o'

hairetu[8]='\0'


と格納しているのと


同様な構造となっています。」


ソーラー

「へぇ~ 面白いシステムだね


char hairetu[100]="nekonekoneko";(こちらは配列hairetu)



char*hairetu="nekonekoneko";(こちらはポインタ変数hairetu)


が実行されるとき


文字データを格納するのに同じ名前の配列変数

hairetu[0]

hairetu[1]

hairetu[2]

hairetu[3]

hairetu[4]

hairetu[5]

hairetu[6]

hairetu[7]

hairetu[8]


をつかっているんだ~


まあ おんなじhairetuという名前を使っているからね


ま、そういうこともあるかな?」


アレサ「このあとのエピソードで述べることになりますが


同じ名前の配列変数を使っていますが・・・


char hairetu[]="nekonekoneko";(こちらは配列hairetu)


によって形成される

hairetu[0]

hairetu[1]

hairetu[2]

hairetu[3]

hairetu[4]

hairetu[5]

hairetu[6]

hairetu[7]

hairetu[8]


char* hairetu="nekonekoneko";(こちらはポインタ変数hairetu)


によって形成される


hairetu[0]

hairetu[1]

hairetu[2]

hairetu[3]

hairetu[4]

hairetu[5]

hairetu[6]

hairetu[7]

hairetu[8]


は名前が同じでも


アドレスがことなっている


つまり


文字データを格納するメモリの場所が異なっています」


ソーラー「ははあ


つまり


配列とポインタ変数を使った場合では


文字列データを格納するメモリがちがうということなんだね



これが

char hairetu[]="nekonekoneko";(こちらは配列hairetu)

char* hairetu="nekonekoneko";(こちらはポインタ変数hairetu)


の違いか・・・


というか 


       😝 それだけのことだったりして 😝


な~んてね


       😝 すこしはちがうんだよね 😝



アレサ 「ふふふふふっ」


ソーラー「ただ何が違うかわからないな・・


両方とも同じ文字列データ"nekoneko"が


配列変数

hairetu[0]

hairetu[1]

hairetu[2]

hairetu[3]

hairetu[4]

hairetu[5]

hairetu[6]

hairetu[7]

hairetu[8]


hairetu[0]='n'

hairetu[1]='e'

hairetu[2]='k'

hairetu[3]='o'

hairetu[4]='n'

hairetu[5]='e'

hairetu[6]='k'

hairetu[7]='o'

hairetu[8]='\0'


と格納されているけど


配列hairetuを使った時と

ポインタ変数hairetuを使った時では


データを格納するメモリのアドレスが違う


つまり

配列変数

hairetu[0]

hairetu[1]

hairetu[2]

hairetu[3]

hairetu[4]

hairetu[5]

hairetu[6]

hairetu[7]

hairetu[8]

のアドレスが

配列hairetuを使った時と

ポインタ変数hairetuを使った時では


ちがうんだよね。」


アレサ「はいっ😊」


ソーラー「で

ポインタ変数宣言

char* hairetu="nekoneko";

を使って格納された文字列データ"nekoneko"を表示するときも


配列宣言

char hairetu[]="nekoneko";

を使って格納された文字列データ"nekoneko"を表示するときも


printf(hairetu);や

printf("%s",hairetu);


をもちいる


これは同じだよね。」


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


ソーラー「??なにがちがうのかな?」


ソーラー「ねえ アレサ


printf(hairetu);や

printf("%s",hairetu);


は なにかすっきりとしてる感じがするね


printf(*hairetu);や

printf("%s",*hairetu);


は違和感があるね。」


アレサ「そうです・・ ね」


ソーラー「ふふっねえ、アレサ」


アレサ「はい、ソーラーさん」


ソーラー「まさか 僕らがこのようなことを


やってることになろうとは思いもしなかったよね。




〘〘🐤  🐤  🐤

char hairetu[]="nekoneko";(こちらは配列hairetu)



char* hairetu="nekoneko";(こちらはポインタ変数hairetu)


文字データを格納するのに同じ名前の配列変数


hairetu[0]

hairetu[1]

hairetu[2]

hairetu[3]

hairetu[4]

hairetu[5]

hairetu[6]

hairetu[7]

hairetu[8]


をつかっているんだ~


だけど 


その文字データを格納する配列変数の


アドレスは


配列hairetuの時と

ポインタ変数hairetuのときでは


ちがうんだよ~~



🐤  🐤  🐤〙〙


とかいってるんだものね・・・


これは いったい(*´▽`*)

どうなってるんだろうね


あははははははははははは」


アレサ「うふふ、 うふふふふふ


・・・そうですね。不思議なものです。


私達は


全くプログラミングとは関係ない生活を


おくっていましたもの・・」


ソーラー「


ほんとだよね


それが いつしかこのような楽しい生活が待っていたわけだ。」


アレサ 「そうですね」


ソーラー「よ~し、この調子で


このカクヨム内で、さらにさらに


ボケかますんだ。どんどん進んでいこう。アレサ」


アレサ「はい、ソーラーさん😊 😊 😊


ではでは😊 😊 😊




ポインタ変数hairetuを使って文字列データ"nekoneko"を格納する場合と


配列を使って文字列データ"nekoneko"を格納する場合の違いは


文字列データを格納するメモリのアドレスが違うということ以外ないの?



と おもわれるかもしれないですの



        🌞違いはあんまりないかもです🌞



配列hairetuを使って


文字列データ"nekoneko"を


メモリに格納する場合にはできないのですが


ポインタ変数hairetuを使って


文字列データ"nekoneko"をメモリに格納する場合は


🍓同じポインタ変数名hairetuを使って🍓


次から次へとどんどん新たに別の文字列データを


メモリに格納することができます。


配列hairetuを使って


文字列データ"nekoneko"をメモリに格納する場合と


ポインタ変数hairetuを使って


文字列データ"nekoneko"をメモリに格納する


場合の違いを述べてみたいと思います。


配列hairetuをつかい文字列データ"nekoneko"をメモリに


取り込んだ場合


格納された文字列データを


"nekoneko"から"nekofunnjyatta"に変更しようとして


次のようなプログラムを実行すると


#include <stdio.h>

int main(void){


char hairetu[]="nekoneko";

char hairetu[]="nekofunnjyatta";

/* 配列hairetuに格納された文字列データをnekonekoからnekofunnjyattaに変更しようとしています*/

printf(hairetu);

return 0;

}


Visual Studioの場合

エラー C2374 'hairetu': 再定義されています。2 回以上初期化されています。


EAZY IDECの場合


nekofunnjyatta


という結果になります


(のちほどかたられますが


EAZY IDECの場合は


同じ名前の配列hairetuを再定義することができます


このとき名前は配列hairetuと一緒でも


この2つの配列hairetuは異なる配列となっています


配列hairetuに格納される文字列データが


このように


"nekoneko"


から


"nekofunnjyatta"


になったとしても


この2つの配列hairetuは異なる配列であり


文字列データ"nekoneko"が格納されているメモリと


文字列データ"nekofunnjyatta"が格納されているメモリは


別々のメモリとなりそのメモリのアドレスは異なっています)



Visual Studioの場合では同じ配列名で


char hairetu[]="nekoneko";

char hairetu[]="nekofunnjyatta";


のように

2度配列宣言を実行できないので


プログラムを実行できませんね😊


では


次のようにプログラムを記述してプログラムを実行してみましょう。


#include <stdio.h>

int main(void){


char hairetu[]="nekoneko";

hairetu="nekofunnjyatta";

/* 配列hairetuに格納された文字列データを"nekoneko"から"nekofunnjyatta"に変更しようとしています*/

printf(hairetu);

return 0;

}


コンパイル結果


EAZY IDECの場合

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

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

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


「lvalue」を付け忘れています。のメッセージがでてきて


配列に格納された文字列データを"nekoneko"から"nekofunnjyatta"に変更できません。


いいかえると


配列変数に格納された文字列データを"nekoneko"から"nekofunnjyatta"に変更できません。


Visual Studioの場合


エラー (アクティブ) E0137 式は変更可能な左辺値である必要があります

エラー C3863 配列型 'char [9]' を割り当てることはできません。 5


と表示されプログラムを実行できません。


あるいは


👇のプログラムのように手を加えてみても


#include <stdio.h>

int main(void){


char hairetu[]="nekoneko";

hairetu[]="nekofunnjyatta";/*←[]をhairetuにつけてみました*/

/* 配列hairetuに格納された文字列データをnekonekoからnekofunnjyattaに変更しようとしています*/

printf(hairetu);

return 0;

}


コンパイル結果


EAZY IDECの場合


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

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

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


Visual Studioの場合


エラー C2059 構文エラー: ']'

エラー (アクティブ) E0029 式が必要です


とメッセージがでてきてプログラムを実行することができません。


ですので


配列hairetuに格納された文字列データを"nekoneko"から"nekofunnjyatta"に変更できません。


つまり


char hairetu[]="nekoneko";


を実行して


配列hairetuを作製して


文字列データ"nekoneko"をメモリに格納した場合は


同じメモリに上書きして


文字列データ"nekofunnjyatta"を格納することはできないというわけです






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


文字列データ"nekoneko"を


char* hairetu="nekoneko"のようにメモリに格納したなら


あとから


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


hairetu="nekofunnjyatta";


と記述し


文字列データ"nekoneko"をメモリに格納したあと


さらに別のアドレスのメモリに


文字列データ"nekofunnjyatta"


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



そのとき


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


によってコマンドプロンプト画面に表示される文字列データは


nekonekoからnekofunnjyattaに変更されます。


次のプログラムをみていきましょう。


#include <stdio.h>

int main(void){


char* hairetu="nekoneko";

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

hairetu="nekofunnjyatta";

/* ポインタ変数hairetuを使って文字列データ"nekoneko"をメモリに格納した後、次にポインタ変数hairetuを使って文字列データ"nekofunnjyatta"をメモリに格納しました*/

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

return 0;

}


コンパイル結果


EAZY IDECの場合

nekoneko

nekofunnjyatta


Visual Studioの場合

nekoneko

nekofunnjyatta


このコンパイル結果をみても おわかりになられますように


nekonekoに代わって


nekofunnjyattaが


表示されています


たしかに


nekonekoにかわってnekofunnjyattaを


表示できたのですが


         

        文字列データ"nekoneko"の上に


       文字列データ"nekonekofunnjyatta"が上書きされて


         メモリに格納されているわけではありません。


つまり


普通の変数なら


例えばint型の変数aなら


int a;

a=1;


を実行した後


a=2;を実行すると


変数aに格納されている値は1から2に


上書きされてしまいますが


ポインタ変数をつかって文字列データをメモリに格納する場合では


char* hairetu="nekoneko";

を実行して

メモリに

文字列データ"nekoneko"を格納したあと


さらに


hairetu="nekofunnjyatta";

を実行して


メモリに

文字列データ"nekofunnjyatta"を格納したなら


文字列データ"nekofunnjyatta"は文字列データ"nekoneko"とはちがう


アドレスのメモリに格納されていきます。


そのときの


文字列データ"nekoneko"と文字列データ"nekofunnjyatta"の


格納されているメモリのアドレスはどうなっているか


それを確かめてみますね。


#include <stdio.h>


int main(void){

char* hairetu="nekoneko";

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

/*文字列データ"nekoneko"が格納されているメモリのアドレスを表示します*/


hairetu="nekofunjytta";/*ここでポインタ変数hairetuをつかって新たに"nekoneko"が格納されているメモリとは別のメモリに文字列データ"nekofunjytta"を格納してきました*/


printf("%p\n",hairetu);/*文字列データ"nekofunjytta"が格納されているメモリのアドレスを表示します*/

return 0;

}


コンパイル結果


EAZY IDECの場合


00402000  ( 文字列データ"nekoneko"が格納されているメモリのアドレス)

0040200D  ( 文字列データ"nekofunjytta"が格納されているメモリのアドレス)

 

Visual Studioの場合

00277CE0 ( 文字列データ"nekoneko"が格納されているメモリのアドレス)

00277CEC ( 文字列データ"nekofunjytta"が格納されているメモリのアドレス)


😽😼😽😼😽😼😽😼😽😺😽😼😽😼😽😼😽😼😽😺

ここで以前のエピソードの復習となりますが


これらのアドレス


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

0040200Dは文字列データ"nekofunjytta"の先頭の'n'を格納しているメモリのアドレスを


あらわしています。

このとき

アドレス00402000のメモリには文字データ'n'が格納されています

アドレス00402001のメモリには文字データ'e'が格納されています

アドレス00402002のメモリには文字データ'k'が格納されています

アドレス00402003のメモリには文字データ'o'が格納されています

アドレス00402004のメモリには文字データ'n'が格納されています

アドレス00402005のメモリには文字データ'e'が格納されています

アドレス00402006のメモリには文字データ'k'が格納されています

アドレス00402007のメモリには文字データ'o'が格納されています

アドレス00402008のメモリには文字データ'\0'が格納されています


アドレス0040200Dのメモリには文字データ'n'が格納されています

アドレス0040200Eのメモリには文字データ'e'が格納されています

アドレス0040200Fのメモリには文字データ'k'が格納されています

アドレス00402010のメモリには文字データ'o'が格納されています

アドレス00402011のメモリには文字データ'f'が格納されています

アドレス00402012のメモリには文字データ'u'が格納されています

アドレス00402013のメモリには文字データ'n'が格納されています

アドレス00402014のメモリには文字データ'j'が格納されています

アドレス00402015のメモリには文字データ'y'が格納されています

アドレス00402016のメモリには文字データ'a'が格納されています

アドレス00402017のメモリには文字データ't'が格納されています

アドレス00402018のメモリには文字データ't'が格納されています

アドレス00402019のメモリには文字データ'a'が格納されています

アドレス0040201Aのメモリには文字データ'\0'が格納されています


😽😼😽😼😽😼😽😼😽😺😽😼😽😼😽😼😽😼😽😺


この結果より


文字列データ"nekoneko"と文字列データ"nekofunnjyatta"が


それぞれ別のアドレスのメモリに格納されていることがわかります。


つまり古いデータも上書きされずメモリに保存されたままということに


なるのですね


ですので


#include <stdio.h>


int main(void){

char* hairetu="nekoneko";

hairetu="nekofunjytaa";

hairetu="nekodaisuki";

hairetu="nekokawaii";

hairetu="nekouresii";

hairetu="nekonyaonn";

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

return 0;

}


コンパイル結果

nekonyaonn


👆このプログラムのように


どんどんポインタ変数hairetuを使って


文字列データ"nekoneko"とは別の文字列データを別のメモリに


格納していったとします


コンパイル結果をみると


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

により

printf出力表示されるのは


最後にメモリに格納された文字列データ"nekonyaonn"の


nekonyaonnとなります



#include <stdio.h>


int main(void){

char* hairetu="nekoneko";

hairetu="nekofunjytaa";

hairetu="nekodaisuki";

hairetu="nekokawaii";

hairetu="nekouresii";

hairetu="nekonyaonn";

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

return 0;

}


#include <stdio.h>


int main(void){

char* hairetu;

hairetu="nekoneko";

hairetu="nekofunjytaa";

hairetu="nekodaisuki";

hairetu="nekokawaii";

hairetu="nekouresii";

hairetu="nekonyaonn";

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

return 0;

}


と書き換えることができます


このプログラム


では何が行われているのかというと


まず


ポインタ変数宣言


char* hairetu;


により作製される


ポインタ変数hairetuに


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


代入されます。


次に


hairetu="nekofunjytaa";


が実行されると


ポインタ変数hairetuに格納されている


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


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


が上書きされて代入されます。



🍓🍓🍓🍓🍓🍓🍓🍓🍓🍓🍓🍓🍓🍓🍓🍓🍓🍓🍓🍓🍓🍓


        🌞ここが重要なポイントです🌞



文字列データ"nekoneko"は文字列データ"nekofunjytaa"に上書きされませんが


🌞ポインタ変数hairetu🌞


に格納されている


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



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


に上書きされるのです


🍓🍓🍓🍓🍓🍓🍓🍓🍓🍓🍓🍓🍓🍓🍓🍓🍓🍓🍓🍓🍓🍓


次に


hairetu="nekodaisuki";


が実行されると



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


文字列データ"nekofunjytaa"を格納しているメモリの🍓アドレス🍓に


かわり


文字列データ"nekodaisuki"を格納しているメモリの🍓アドレス🍓が


上書きされて代入されます。


つまり


ポインタ変数hairetuに


新たに


文字列データ"nekodaisuki"を格納しているメモリの🍓アドレス🍓が


上書きされます。


このときも


文字列データ"nekofunjytaa"は文字列データ"nekodaisuki"に上書きされることはありませんが


ポインタ変数hairetuに格納していた


文字列データ"nekofunjytaa"を格納しているメモリの🍓アドレス🍓は


文字列データ"nekodaisuki"を格納しているメモリの🍓アドレス🍓に上書きされます


つまり


ポインタ変数hairetuの格納しているアドレスは


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


から


文字列データ"nekodaisuki"を格納しているメモリの🍓アドレス🍓に


かわります。


こうして

hairetu="nekoneko";

hairetu="nekofunjytaa";

hairetu="nekodaisuki";

hairetu="nekokawaii";

hairetu="nekouresii";

hairetu="nekonyaonn";


が実行されていくと


最後にポインタ変数hairetuに格納されることになるアドレスは


hairetu="nekonyaonn";

により

文字列データ"nekonyaonn"


が格納されたメモリのアドレスとなるのです。


ポインタ変数hairetuに格納されることになるアドレスは


文字列データ"nekonyaonn"


が格納されたメモリのアドレスとなるので


ポインタ変数hairetuに格納されているアドレスのメモリに


格納されている文字列データを表示する命令文


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


が実行されると


コマンドプロンプト画面に表示される文字列は


文字列データ"nekonyaonn"の


nekonyaonn


となります。


このように


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



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


文字列データを表示する働きがあります



このとき

"nekonyaonn"以外の文字列データ


"nekoneko"

"nekofunjytaa"

"nekodaisuki"

"nekokawaii"

"nekouresii"



別のアドレスのメモリに格納されていますが


ポインタ変数hairetuを用いた


printf(hairetu);

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

をつかって


文字列

nekoneko

nekofunjytaa

nekodaisuki

nekokawaii

nekouresiiを


コマンドプロンプト画面に表示することはできなくなっています。


なぜなら


ポインタ変数hairetuは文字列データ"nekonyaonn"を格納しているメモリのアドレスを


格納しているからです



いかがでしたか


いままでの説明は簡易番となっていますが


  「配列の代わりにポインタ変数をつかって文字列データをメモリに格納する」


意外と簡単だったのではないでしょうか?」






おまけ




#include <stdio.h>

int main(void){


char* hairetu="nekoneko";

printf(hairetu);

return 0;

}

コンパイル結果


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



このプログラムでは


char* hairetu="nekoneko";


のように


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


文字列データ"nekoneko"をメモリに格納しています


文字列データ"nekoneko"をコマンドプロンプト画面に表示しようとして


printf(hairetu);

を実行すると


コンパイル結果


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



nekoneko

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


がくっついて表示されます。


それを避けるために


printf(hairetu\n);


と記述するとコンパイルエラーが出てしまいます。


ですので


printf(hairetu);


と記述するしかなく


コンパイル結果は


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


となり


nekoneko

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


のように改行することができません。


では

配列hairetuを使ってchar hairetu[] に


文字列データ"nekoneko"をメモリに格納した場合はどうなるのでしょうか?


#include <stdio.h>

int main(void){


char hairetu[]="nekoneko";

printf(hairetu\n);


return 0;

}

コンパイル結果


EAZY IDECの場合


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

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

「\」の使い方が間違っています。\ を文字列の外で使っていないかどうか確認してください。


Visual Studioの場合


エラー (アクティブ) E0007 認識されないトークンです

エラー C2146 構文エラー: ';' が、識別子 'n' の前に必要です。

エラー C2146 構文エラー: ')' が、識別子 'n' の前に必要です。

エラー C2059 構文エラー: ')' Project8

エラー C2017 エスケープシーケンスの使い方が正しくありません。

エラー C2065 'n': 定義されていない識別子です。


とエラー文が表示されプログラムを実行できません。



printf(hairetu\n);から\nを取り除いて


コンパイルしてみると


#include <stdio.h>

int main(void){


char hairetu[]="nekoneko";

printf(hairetu);/*ここの部分で\nを取り除きました*/


return 0;

}


コンパイル結果

(EAZY IDECの場合)

(Visual Studioの場合)


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


とコマンドプロンプト画面に表示され


無事にプログラムが実行できています。


配列

ポインタ変数を使った場合

の両方とも


printf(hairetu\n);


は使用することができないので


printf(hairetu);


と記述するしかなく


コンパイル結果


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


nekoneko

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


がくっついてコマンドプロンプト画面に表示されてしまいます


では


nekoneko

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


と改行させてコマンドプロンプト画面に表示させるためには本文でも使われていたように


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


と記述するしか方法はないのでしょうか?


あるんです😊


printf(hairetu);


をつかって


nekoneko

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


のように改行してコマンドプロンプト画面に表示する方法が 😊


その方法とは


配列やポインタ変数を使って文字列データ"nekoneko"をメモリに


取り込む際


char hairetu[100]="nekoneko";

char* hairetu="nekoneko";


と記述するのではなく


char hairetu[100]="nekoneko\n";

char* hairetu="nekoneko\n";


と\nをnekonekoにとりつけます


そうすると



🐤char hairetu[]="nekoneko\n";


を実行した場合



#include <stdio.h>

int main(void){


char hairetu[]="nekoneko\n";

printf(hairetu);/*ここの部分では\nはhairetuにくっついていませんね*/


return 0;

}


コンパイル結果


nekoneko

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



🐥char* hairetu="nekoneko\n";

を実行した場合


#include <stdio.h>

int main(void){


char* hairetu="nekoneko\n";

printf(hairetu);/*ここの部分で\nを取り除いています*/


return 0;

}


コンパイル結果


nekoneko

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



ともに


nekoneko

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


と改行できます


これで


printf(hairetu);


もつかえますね。



















































































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

作者を応援しよう!

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

応援したユーザー

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

新規登録で充実の読書を

マイページ
読書の状況から作品を自動で分類して簡単に管理できる
小説の未読話数がひと目でわかり前回の続きから読める
フォローしたユーザーの活動を追える
通知
小説の更新や作者の新作の情報を受け取れる
閲覧履歴
以前読んだ小説が一覧で見つけやすい
新規ユーザー登録無料

アカウントをお持ちの方はログイン

カクヨムで可能な読書体験をくわしく知る