2020年10月9日金曜日

ある奇妙なプログラムのふるまいについて

 まずはこの,Cのプログラムを見ていただきたい.

#include <stdio.h>


int main() {

  int a = 0;

  printf("Please type an integer number: ");

  scanf("%d", &a);

  a = a * 100;

  printf("Your number * 100 = %d\n", a);

}

このプログラムが,hogehoge.cというファイル名で保存されているとする.

コンパイルして実行してみよう.入力した整数を100倍した計算結果が出力される.

$ gcc hogehoge.c 

$ ./a.out

Please type an integer number: 123

Your number * 100 = 12300

ところで,次のようなプログラムを書いた人がいた.

#include <stdio.h>

  

int main() {

  int a = a * 100;

  printf("Please type an integer number: ");

  scanf("%d", &a);

  printf("Your number * 100 = %d\n", a);

}

変数宣言と,代入演算子「=」を用いた自己代入を混同してしまったらしい.珍しいミスだなと思いつつも,コンパイルしてみた.ところがどっこい,これ,なんと,エラーにならないじゃない?

$ gcc hogehoge.c 

$ ./a.out

Please type an integer number: 123

Your number * 100 = 123

もちろん計算結果は100倍にはならない.scanfprintfの間に100倍する操作が抜けているので,まあ,そりゃ,そうなるだろう.しかし,プログラムとしてはエラーにならず動作する.

次に,-Wallを付けてコンパイルしてみた.

$ gcc -Wall hogehoge.c 

hogehoge.c:4:11: warning: variable 'a' is uninitialized when used within its own initialization

      [-Wuninitialized]

  int a = a * 100;

      ~   ^

1 warning generated.

変数aが初期化されずに使われているという警告が出た.なぜこのような解釈になるのか.まず,変数宣言されて(int a),次に,初期化せず使われた(a * 100)ということになるらしい.なるほど,面白い.

手続き型のプログラミングを前提としているので,「構造化プログラミングが教える連結・分岐・反復のうち,連結(つまり上から順番に実行するということ)はわざわざ教えんでもええやろう,hello worldから始まって,少しずつプログラムを習ってきているうちに,みな自然と理解してるよな?」と思っていた.しかし,順番をあまり意識することのない関数型や宣言型的な発想に素で至ることもあるんだなあと,その自由な発想力に少し驚いた次第である.

ん?なんかおかしいぞ?

  

0 件のコメント:

コメントを投稿