C言語 プログラムを3か月で身につけるための第1週前半でやるべきこと

  • このエントリーをはてなブックマークに追加
Pocket

C言語を3か月で身につけてるための詳細を、これも記憶を呼び起こしながらですが、書いていきたいと思います。

大まかなスケジュールはこちらのページを参照ください。

———————————————————————–
C言語 プログラムを3か月で身につけるスケジュール
———————————————————————–

早速ですが、第1週前半でやるべきとを解説します。
第1週前半は、変数宣言、代入文、演算子、演算結果の表示です。

第1週前半

変数宣言

これができなければ、どうにもなりませんので、一番始めに覚えてしまいましょう。

まずは、型について示します。

意味 サイズ(Byte)
char 文字 1
unsigned char 符号無し文字 1
short 短い整数 2
unsigned short 符号無し短い整数 2
int 整数 2または4
unsigned int 符号無し整数 2または4
long 長い整数 4
unsigned long 符号無し長い整数 4
float 単精度浮動少数型実数 4
double 倍精度浮動少数型実数 8
void 空を表す(関数宣言のみ)

(注1)例えば、1Byteは8bitで2の8乗で表せられる数値までを扱うことができます。2byteだと2の16乗ということになります。
(注2)int, unsigned intサイズはコンパイラによって異なりますので、shortやlongを使用することをお勧めします。
(注3)サイズについては次のコードで知ることができます。

     #include <stdio.h>

     main() {
        printf( "charのサイズ : %d", sizeof(char) );
     }

     出力結果
     charのサイズ : 1

char型、unsigned char型を文字というふうに書きましたが、文字を扱うのに使用することが多いということであり、数値に使用してはいけないということではありません。
ただ、扱える範囲が符号なしだと0~255、符号ありだと-128~127となるため、それを考慮して扱わなくてはなりません。

組み込みマイコンだと、容量が限られているので、各変数の扱いを吟味し、char型、unsigned char型を用いることは多いです。

では、なぜ文字と書いたかというと、文字はプログラムの内部ではASCIIコードと言われるデータに変換されて、数値で処理されます。その範囲がcharで収まるので、文字と書いた次第です。

変数の宣言の仕方はシンプルです。

char a;
unsigned char b;
short c;
unsigned short d;
int e;
unsigned int f;
long g;
unsigned long h;
float i;
double j;

このように、変数名の前に使用する型を記述するだけです。変数名は便宜上、a,b,cとかにしましたが、プログラムに適した変数名をつける習慣を身につけてください。そうすることで、第3者や後から見返したときに、変数名から何を表しているのかが、プログラムを読まなくても想像ができます。

voidについては変数で定義することがありません。また、long longという宣言もできるようになっているようですが、組み込みマイコンでは処理速度が求められます。

したがって、桁の大きい数値の扱いは処理速度の低下につながるので現在のところ、使用することはありません。少なくとも、私は使用していません。

また、float型、double型も組み込みマイコンでは扱いません。

ちょっと余談が多くなってしまいましたが、変数の宣言は「型 + 変数名」と記述すればいいです。どの型を選択するかは、その状況に応じて決めていくので、ここではどの型にしなさいと言うことはできません。

代入文

事項で解説する演算子の1つ代入演算子と呼ばれるものを使用して、数値を代入します。
書き方は、変数宣言と同様、シンプルです。

short a;
double b;

a = 20;
b = 3.1415926;

このように、「=」を使って記述します。代入したい変数を「=」の左側に、代入するデータを「=」の右側に記述します。

C言語プログラムの世界の「=」は、算数・数学の等しいと言う意味ではありませんので、混同しないように注意してください。

それが、理解できていないと、

a = b;
a = a + 1;

という文の意味ができないことになってしまいます。

一応、言っておくと、1行目は「aにbの値を代入する」、2行目は「現在のaの値に1を足して、その値をaに代入する」、 要するに「aの値を1増やす」です。

決して、「aはbと等しい」とか、「aとaに1足した値が等しい」ということではないので、間違えないようにしてくださいね。

実は、私はこの処理を始めてみたとき、訳がわかりませんでした。どうしても、数学の概念が入るからです。だから、あなたはこの処理を始めて見たのなら、訳がわからないと思います。

C言語プログラムは、例え数学と同じ記号を使っていても、意味が全く違うモノだということを認識しておけば大丈夫です。

しかし、代入文は「=」を使って表すんだということはおわかりいただけたかと思います。代入演算子については事項でもう少し解説します。

演算子・演算結果の表示

C言語のプログラムの演算子は算術演算子、ビット演算子、関係演算子、等値演算子、論理演算子、シフト演算子、代入演算子とあります。

こんなにあるんかよと思ったかもしれませんが、1つ1つは対した事ありませんので、安心してください。

また、演算結果の表示についても各演算子のところで、例を使って解説していこうと思います。

では、順に解説していきます。

算術演算子

+,-,*,/,% があり、それぞれ加算、減算、乗算、除算、剰余計算を表します。 例を示したほうが、わかりやすいと思うので、簡単なプログラムを書いてみました。

(例) #include <stdio.h>

     main() {
        int x, y;  /* 算術演算させるための変数 */

        /* 算術演算させる数値の格納(ユーザがキーボードで入力) */
        /* ここでは文字入力されたときの処理を入れてないので   */
        /* 数字以外のものを入力するとプログラムは暴走する。   */
        /* また、整数のみしか扱っていない。                   */
        printf( "x = " );
        scanf( "%d", &x );
        printf( "y = " );
        scanf( "%d", &y );

        /* 算術演算の結果を出力 */
        printf( "x + y = %d\n", x + y );
        printf( "x - y = %d\n", x - y );
        printf( "x * y = %d\n", x * y );
        if ( y == 0 ) {
           printf( "割り算はできません。\n" );
           printf( "余りを求められません。\n" );
        } else {
           printf( "x / y = %d\n", x / y );
           printf( "x / y の余りは%d\n", x % y );
        }
     }

     入力        
     x = 7 Enter        x = 5 Enter 
     y = 3 Enter        y = 0 Enter

     出力結果
     x + y = 10         x + y = 5
     x - y = 4          x - y = 5
     x * y = 21         x * y = 0
     x / y = 2          割り算はできません。
     x / y の余りは1    余りを求められません。

例文中の/* */で囲われた部分はコメント文ですので、プログラムとは関係ありません。 通常、処理を記述するときに、何をしているのかをこのようにコメント文で解説しておきます。

そうすると、自分で後で見たときや第3者が見たときに、プログラムが理解しやすいですよね。 なので、コメント文は意識して書くようにしましょう。

ここでは、計算結果を一旦別の変数に代入してから、それを表示させるということはしていません。

また、表示方法はprintfという標準関数と呼ばれるものを用いて表示させています。 入力のときにも表示させており、ユーザがキーボードで入力し、リターンキーを押されたら、 そのときの数値をscanfという標準関数で読み込んで、変数xに設定します。

数値を入れないとプログラムが暴走するとコメントしているのは、scanfで読み込んでいるのが %dという整数型で読み込む指示をしているためです。

したがって、ここに文字が入力されると、 プログラムがそれを認識できずに、プログラムが暴走するのです。 これを回避しようと思ったら、%sという文字で読み込んで、その後、プログラム内部で数値に 変換できるか判定し、変換できるなら数値にするというようなことをする必要があります。

これがエラー処理、想定外の入力があった場合の対応ということになります。 ここでは、算術演算子の使い方を理解するための項目ですので、エラー処理については、 この段階では考えなくていいです。

あなたが、この例のプログラムをコピペして、実行したときに、暴走させてしまったら、 Ctrl-Cを押して、強制的にプログラムの実行を停止させてください。

話を戻して、演算結果を出力するところで、各種演算させているのがわかるでしょうか? 「x + y」「x – y」「x * y」「x / y」「x % y」の部分です。

「x + y」のprintf文について解説すると、” ”で囲まれた部分がコンソールに表示されます。 そして、ここでも%dと書かれています。ここに” ”以降に書かれた「x + y」の演算結果を 反映します。

なので、出力結果は「x + y = 10」となるわけです。 割り算ですが、0で割れない事は、わかりますよね? 0で割ろうとするとプログラムが暴走します。

そうならないように、第1週後半編で解説する if文で場合分けをしているのです。 また、変数が整数型、%dでの表示ということで、割り算の結果は少数では出てきません。 切り捨てられた値が表示されます。

したがって、xよりyのほうを大きい値にすると、 「x / y」は「0」と表示されます。

ビット演算子

&,|,^,~ があり、それぞれ論理積、論理和、排他的論理和、ビット反転を表します。 ここも例を使って解説していきます。

(例) #include <stdio.h>

     main() {
        unsigned char x, y;  /* ビット演算させるための変数 */

        /* ビット演算させる数値の格納(ユーザがキーボードで入力) */
        /* ここでは文字入力されたときの処理を入れてないので     */
        /* 数字以外のものを入力するとプログラムは暴走する。     */
        /* また、整数のみしか扱っていない。                     */
        printf( "x = " );
        scanf( "%d", &x );
        printf( "y = " );
        scanf( "%d", &y );

        /* ビット演算の結果を出力 */
        printf( "x & y = %d\n", x & y );
        printf( "x | y = %d\n", x | y );
        printf( "x ^ y = %d\n", x ^ y );
        printf( "~x = %d  ~y = %d\n", ~x, ~y );
     }

     入力
     x = 7 Enter (2進数で00000111)
     y = 3 Enter (2進数で00000011)

     出力結果
     x & y = 3 (2進数で00000011)
     x | y = 7 (2進数で00000111)
     x ^ y = 4 (2進数で00000100)
     ~x = 248  ~y = 252 (2進数でそれぞれ11111000, 11111100)

ビットのイメージがつきにくいと思います。我々が一般的に扱っている数値は10進法というもので、0~9までを1桁で扱い、 9の後に1増えると桁が増えて10になりますよね。

これが、ビットで扱う場合、2進法になります。どういうものかカンのいいあなたならわかるかもしれません。

そうです。0と1しかない世界です。なので、1の次は2という概念がないので、桁が1つ上がり10となります。

例えば、10進法で「7」を2進法で表すと「00000111」となります。桁を8桁としました。これが1バイトと言う単位になり、 例のプログラムのunsinged char型のサイズです。

ビット演算を行う場合は、2進数で表したものをイメージしながら、得られる結果を考えなくてはなりません。

まず、「&」の論理積ですが、これは2つの数値の該当ビットが両方とも1のとき1という結果が得られます。どちらか一方が 0だと、論理積の結果は0となります。

次に「|」の論理和ですが、これは「&」と逆のイメージで、どちらか一方のビットが1なら、結果は1になります。両方0の場合のみ、 結果は0となります。

「^」の排他的論理和は、少しわかりにくいですが、両方ともおなじ値(0でも1でも)なら、結果は0になります。互いに 違う値(1と0)のときに、結果が1となります。

最後に「~」のビット反転ですが、これは文字通り、1と0のビットを反転させます。

ここで、改めて、例のプログラムの入力と出力結果を見てもらえば、出力結果の内容が納得できるはずです。こういうのを使うのかと思われるかもしれませんが、かなり使いますので、覚えておいてください。

関係演算子、等値演算子、論理演算子

<,<=,>,>= が関係演算子、==,!= が等値演算子、&&,||,! が論理演算子です。

これらは主に条件文で用いられます。大小を比較するには関係演算子、値が等しいかどうかを判定するには等値演算子、かつ、または、否定を扱うのが論理演算子です。

ここも、例を使って解説していきます。

(例) #include <stdio.h>

     #define MAX 255
     #define MIN   0

     main() {
        int  x, y;  /* 演算させるための変数 */
        int  flag;

        /* 演算させる数値の格納(ユーザがキーボードで入力) */
        /* ここでは文字入力されたときの処理を入れてないので     */
        /* 数字以外のものを入力するとプログラムは暴走する。     */
        /* また、整数のみしか扱っていない。                     */
        printf( "x = " );
        scanf( "%d", &x );
        printf( "y = " );
        scanf( "%d", &y );
        printf( "算術演算   : 0\n" );
        printf( "ビット演算 : 1\n" );
        printf( "Input No.  : " );
        scanf( "%d", &flag );

        /* エラー */
        if ( flag != 0 && flag != 1 ) {
           printf( "Input No. Error\n" );
        }
        /* 算術演算 */
        else if ( flag == 0 ) {
           printf( "x + y = %d\n", x + y );
           if ( x < y )  printf( "y - x = %d\n", y - x );
           else          printf( "x - y = %d\n", x - y );
           prtinf( "x * y = %d\n", x * y );
           if ( x >= y && y != 0 )       printf( "x / y = %d 余り %d\n", x / y, x % y );
           else if ( x <= y && x != 0 )  printf( "y / x = %d 余り %d\n", y / x, y % x );
        }
        /* ビット演算 */
        else if ( flag == 1 ) {
           if ( !(x < MIN || x > MAX || y < MIN || y > MAX) ) {
              printf( "x & y = %d\n", x & y );
              printf( "x | y = %d\n", x | y );
              printf( "x ^ y = %d\n", x ^ y );  
           } else {
              printf( "ビット演算はしませんでした。\n" );
           }
        }
     }

     入力
     x = 7 Enter             x = 2 Enter             x = 7 Enter             x = 256 Enter
     y = 3 Enter             y = 7 Enter             y = 3 Enter             y = 3   Enter
     算術演算   : 0          算術演算   : 0          算術演算   : 0          算術演算   : 0
     ビット演算 : 1          ビット演算 : 1          ビット演算 : 1          ビット演算 : 1
     Input No.  : 0 Enter    Input No.  : 0 Enter    Input No.  : 1 Enter    Input No.  : 1 Enter

     出力結果
     x + y = 10              x + y = 9               x & y = 3               ビット演算はしませんでした。
     x - y = 4               y - x = 5               x | y = 7
     x * y = 21              x * y = 14              x ^ y = 4
     x / y = 2 余り 1        y / x = 3 余り 1

第1週後半編で解説するif文が大量に出てきていますが、演算子の説明のためなので、ご容赦ください。

逆にここで、if文がわかってしまえば、次の第1週後半編が楽になります。

#defineと記述がありますが、これはMAXとMINをあらかじめ、決められた数値にしておくという定義文です。 直接プログラム処理の部分に数値を書いてもいいのですが、もし、変更があった場合、それらの数値を すべて変更する必要がありますよね。

しかし、このように定義文を記述しておくと、その定義している数値を変更するだけで、それを参照している箇所は 自動的反映されるので、変更漏れがなくなります。そういうメリットがあるため、例に記述しました。

今回は、算術演算するのかビット演算をするのかを選択させるようにしました。先の例をあわせたものと イメージしてもらえばいいです。

まず、最初にデータと算術演算かビット演算かを選択する入力があります。選択されたデータをflagに格納しています。

このとき、0か1が入力されればいいですが、2以上の数値を入力されると困るので、等値演算子の「!=」と論理演算子の「&&」を使って、 flagが0か1でないことを条件にしています。条件を満たすと、「Input No. Error」と出力して終了するようにしています。

そして、「flag == 0」と等値演算子を使用し、算術演算を行っています。ここで、注目してもらいたいのはxとyの値の関係性 を見ているところです。

足し算、掛け算はそのまま計算していますが、引き算は結果が0より大きくなるようにし、割り算は0で 割らない工夫をしています。この場合、xもyも0の場合は何もしないようになっています。

「flag == 1」の場合はビット演算を行うようにしています。しかし、数値が所定の数より大きかったり、小さかったり 下場合はビット演算をしないようにしています。

ちょっとややこしい記述の仕方をしていますが、論理演算子をすべて 登場させたかったので、あえて書きました。

if文をまともに読むと次のようになります。

「xが0より小さいか、xが255より大きいか、yが0より小さいか、yが255より大きいということはない」、要するに、 「xは0から255 かつ yは0から255である」 ということです。

シフト演算子

<<,>> がそれぞれ左シフト、右シフトを行う命令です。

左にシフトするときは最下位ビットに0が詰められ、右にシフトするときは符号無しのときは最上位ビットに0が詰められ、符号付きのときは最上位ビットにはシフト前の最上位ビットがコピーされるか、0が詰められます。それは処理系に依存します。

(例) #include <stdio.h>

     main() {
        unsigned char x, y;  /* シフト演算させるための変数 */

        /* シフト演算させる数値の格納(ユーザがキーボードで入力) */
        /* ここでは文字入力されたときの処理を入れてないので     */
        /* 数字以外のものを入力するとプログラムは暴走する。     */
        /* また、整数のみしか扱っていない。                     */
        printf( "x = " );
        scanf( "%d", &x );
        printf( "y = " );
        scanf( "%d", &y );

        /* シフト演算の結果を出力 */
        printf( "x << y = %d\n", x << y );
        printf( "x >> y = %d\n", x >> y );
     }

     入力
     x = 8 Enter (2進数で00001000)
     y = 3 Enter

     出力結果
     x << y = 64 (2進数で01000000)
     x >> y = 1  (2進数で00000001)

シフト演算子は値をシフトするというものですが、2進数で桁を上げたり、下げたりするということです。

シフト演算子を使わなくても、2の(シフト量)乗で掛けたり、割ったりすれば、同じ結果が得られます。

例えばシフト量が2なら、元の値に4を掛けたり、割ったりしたらいいのです。 では、なぜシフト演算子があるのかというと、シフト演算のほうが処理速度が速いからです。

組み込みマイコンでは処理速度が求められるため、少しでも演算を早くしたいのです。 したがって、シフト演算で済むところはシフト演算を使うようにします。

代入演算子

先の項目代入文のところで解説しましたが、ここで、代入演算子の一覧を下記に示します。

構文 意味
x = y x に y の値を代入する
x += y x = x + y (x に y の値を足し込む)
x -= y x = x – y (x から y の値を引く)
x *= y x = x * y (x に y の値を掛ける)
x /= y x = x / y (x を y の値で割る)
x %= y x = x % y (x を y で割った余りを得る)
x <<= y x = x << y (x を y ビット左シフト)
x >>= y x = x >> y (x を y ビット右シフト)
x &= y x = x & y (x の y とのビット積を得る)
x |= y x = x | y (x の y とのビット和を得る)

代入文のところでは1行目の「=」を使うところのみの解説でした。一覧表を見てもらえば、わかりますが、これだけの記述法があるのです。特に使わなくても「=」だけで書けますが、知っておいて損はないと思います。

一覧表の意味を見てもらえば、ほぼわかると思います。
すべて、元のxの値に演算をして、新たなxとするということです。

気をつけていただきたいのは、演算子の右側です。ここではyしかないので、特に問題ないですが、このあと、さらに演算子が続く場合は、あなたがどのような演算をさせたいのかで、書き方が異なります。

例えば、x += y * z; とした場合、xには元のxの値 + yとzの積の値が代入されますね。でも、本当はxとyを足した後にzをかけて、それを新たなxとしたい場合は、この書き方はできません。

そういう場合は、x = (x + y) * z; と書くしかありません。

まとめ

C言語のプログラムを3か月で身につけるための第1週前半でやるべきことを解説しました。

・型の種類と変数宣言の仕方
・代入文の使い方と意味
・演算子の使い方と意味
・printfでのコンソール表示

ボリュームがあるように思いますが、共通しているところ、お互いに干渉しあって必要になっているところがあったと思います。プログラムは、各文法だけ並べても動作しません。

これらを組み合わせて、動作させる事ができます。これだけでも算術演算プログラムは作れるようになります。

まずはイメージをつかんで、余力があれば、実際にプログラムをコピペして動かしてみてください。

3日以内にマスターし、C言語のプログラムを3か月で身につけるための第1週後半でやるべきことへ進んでください。

  • このエントリーをはてなブックマークに追加

コメントを残す

*