グローバル変数bを自作関数の引数の変数aに代入した場合も値渡しとなるためグローバル変数bは自作関数の操作を受けることはなくグローバル変数bに格納されている数値は変更されません。

#include<stdio.h>


void f(int a) {

a=a+1;

}


int main(void){

int b=2;

printf("%d\n",f(b));

printf("%d\n",b);


return 0;

}

コンパイル結果


EAZY IDECの場合

3

2


Visual Studioの場合


E0070 不完全な型は使用できません

C2664 'int printf(const char *const ,...)': 引数 2 を 'void' から '...' へ変換できません。


と表示されます。


このプログラムがVisual Studioで実行できないのは


自作関数の


void f(int a) {

a=a+1;

}

の表記に

問題があるからなのです。


ここでは


自作関数f(int a) に戻り値が格納されないよう


voidが記述されています。


さらに


return a;


などのように


戻り値を返すように記述されていないので



もちろん


f(int a)


のint aに


main関数で変数宣言された


変数aを代入して


f(a);


を実行し


a=a+1;


がおこなわれたあとの


aの値


が戻り値としてf(a)に返ることはありません。


ですので


void f(int a) {

a=a+1;

}

が実行されても

f(int a)には

戻り値が戻ることhaarimasenn


自作関数f(b);


が実行されても


f(b)は戻り値をもつことがないので


printf("%d\n",f(b));


と記述されても


f(b)の持つ値が存在せず


ビルドエラーが生じてしまうというわけです。


そのことを


Visual Studioは


警告してくれているのですね。



この不完全なプログラムでも

EAZY IDECなら実行できてしまうというわけです。


そこで


自作関数f(int a) に


a=a+1;


がおこなわれたあとの


aの値


が戻り値として


返るよう


void f(int a) {

a=a+1;

}

の部分を


int f(int a) {

a = a + 1;

return a;

}


と記述し直します。


a=a+1;


が実行された後の


aの値が戻り値として f(int a)に戻るよう


return a;


を追加し


整数値である戻り値が格納されるよう


void型からint型に変更したというわけですね。


#include<stdio.h>


int f(int a) {


a = a + 1;

return a;

}


int main(void) {


int b = 2;


printf("%d\n",f(b));

printf("%d\n", b);


return 0;

}


コンパイル結果

EAZY IDECの場合

3

2


Visual Studioの場合

3

2



ソーラー 「ようやく正しく


コンパイル結果が表示されるようになったね。


この訂正されたプログラムでは


main関数内で定義された変数bを


f(b)と自作関数の引数に代入し


変数bに格納している数値2を自作関数の引数である


変数aに値渡ししています。


つまり


自作関数内でint aにより


作製された変数aという名前の付いたメモリ



main関数内でint b;により


作製された変数bという名前の付いたメモリ


が独立して存在し


変数bという名前の付いたメモリに格納されている


数値2を


変数aという名前の付いたメモリに


渡しているのみなので


a = a + 1;


が実行されても


変数bは自作関数の操作を受けることはなく


変数bに格納されている値は


printf("%d\n",b);


のコンパイル結果をみてもわかるように


int b=2;


と変数宣言、初期化されたときの


b=2のまま変化することはありません。


そこでプログラムを変形し


#include<stdio.h>


int b=2;


int f(int a) {

a = a + 1;

return a;

}


int main(void){


printf("%d\n",f(b));

printf("%d\n",b);


return 0;

}


のように


int b;をプログラムの先頭にもっていき


変数bをmain関数の前で定義したなら


このプログラムのコンパイル結果はどうなるかな?」


アレサ「それはローカル変数bをグローバル変数にするということですね」


ソーラー「そうなんです。変数bをグローバル変数にすれば


グローバル変数宣言

int b=2;

がおこなわれたのなら


グローバル変数bは


それより下の行の


自作関数内でも

main関数内でも


共通して


使用できることになります


このグローバル変数bを


f(b)


と自作関数f(int a)に代入した場合でも


グローバル変数bの持っている値2だけが値渡しされて


グローバル変数bは


自作関数による影響をうけることなく


グローバル変数bの格納している値は2のままとなるのでしょうか?


それとも


int f(int a) {

a = a + 1;

return a;

}



つまり自作関数


f(int a)



グローバル変数bが代入されることにより


b=b+1;


が実行されて


グローバル変数bの格納する値は


2から3に変化するのでしょうか?


それではコンパイル結果はどうなるかな?」


アレサ「どきどきっ💖


bのグローバル変数宣言,初期化を


int b=2;


とプログラムの先頭でおこなった場合


グローバル変数bの格納している値2だけが


自作関数の引数である変数aに値渡し


されるのでしょうか?


グローバル変数bは


main関数内で作製されたローカル変数bと違い


自作関数内でも

main関数内でも


共通して


使用できるので


グローバル変数bが自作関数f(int a)に代入された場合


b=b+1;


が実行されて


グローバル変数bの格納する値は


2から3に変化するようにもおもえます。」


ソーラー「ほんと たのしみだね


では 先程のプログラムを

👇

#include<stdio.h>


int b=2;


int f(int a) {

a = a + 1;

return a;

}


int main(void){


printf("%d\n",f(b));

printf("%d\n",b);


return 0;

}


ソーラー「コンパイルっ」


コンパイル結果

3

2


ソーラー「グローバル変数bを自作関数f(int a)の引数である変数aに


代入した場合も


printf("%d\n",b);


のコンパイル結果をみてもわかるように


グローバル変数bに格納されている値2のみが


自作関数の引数である変数aに値渡しされるので



グローバル変数bに格納されている値は


int b=2;


と変数宣言、初期化されたときの


b=2のまま


グローバル変数bに格納されている値は変化することはないんだ・・」


アレサ「このことは


グローバル変数宣言


int b=2;により


作製された変数bという名前の付いたメモリ



自作関数内でint aにより


作製された変数aという名前の付いたメモリ


が独立して存在していることをしめしています。


変数bという名前の付いたメモリに格納されている


数値2を


変数aという名前の付いたメモリに


渡しているのみなので


a=a+1;


が実行されて


変数aの格納している値が3になったとしても


変数bという名前の付いたメモリに格納されている数値は変化しませんね。


グローバル変数bは自作関数の操作を受けることはなく


グローバル変数bに格納されている値は


printf("%d\n",b);


のコンパイル結果をみてもわかるように


int b=2;


と変数宣言、初期化されたときの


b=2のまま変化することはないのですね。」











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

作者を応援しよう!

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

応援したユーザー

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