Code027: Cプログラミング 〜しっかり基礎を固めようシリーズ 暗黙の型変換編〜

この記事は2002年に書かれたものです。


■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■
【 Webプログラミング Code Sample 】                          Since2001/11/23

                         Code027: Cプログラミング
             〜しっかり基礎を固めようシリーズ 暗黙の型変換編〜

■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■
                                                    Produced by ichikoro.com

           ▼毎週月曜日と金曜日に配信しています。
           ▼等幅フォントでご覧いただくとキレイに見えます。
           ▼登録・解除はこちらから可能です。
               < http://www.ichikoro.com/webp/ >
                  ※バックナンバーへのリンクもあります。
                  ※お友達にもぜひお勧めください(^^)/

─【Contents】───────────────────────────────
    01.Review ................... 前回のおさらい
    02.Guide .................... 暗黙の型変換:なぜこんなことが起きるの?
    03.Guide .................... 暗黙の型変換:C言語には型がある
    04.Guide .................... 暗黙の型変換:型には大きさがある
    05.Guide .................... 暗黙の型変換:大きな器に小さな値
    06.Guide .................... 暗黙の型変換:小さな器に大きな値
    07.Guide .................... 暗黙の型変換:まとめてみましょう!
    08.Guide .................... 次回予告
    09.Question ................. 今週の問題
    10.From Editor .............. 編集後記


                   【 Webプログラミングは毎週2本立て! 】

             ・月曜日版はWebの実際の活用方法などを特集します。
             ・金曜日版はHTMLやCGIなど一つの分野について最初から
              解説する講座になっています。現在はC言語入門です。


こんにちは、編集者の勝部です。

ちょっと前の話題ですが、まだ私が小学生の頃にTV放映が始まった「ドラゴンボール」
がハリウッドで映画化、しかも実写らしいです。どうもスターウォーズと肩をはるも
のになるとか。しかし、一番楽しみなのはキャスティングでしょうか。亀仙人は?ク
リリンは?あれを演じることのできるハリウッドスターって一体誰だ(^^; 

何はともあれ、懐かしの、しかも逆輸入版のキャラクター達がスクリーンで暴れて
いるところ、早く見てみたい物です。

    ・「ドラゴンボール」が米で実写映画化
      http://news.fs.biglobe.ne.jp/topics/200203131940/10800.html

ではでは今週もいってみましょう。


━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
  01.Review  「前回のおさらい」
──────────────────────────────────────

前回は、whileについて解説しました。

Code15でご紹介した下のプログラムも、バッチリ理解できるようになった事と
思います。もし、ちょっとでも不安なところがあるならば、無理に進まずに、
一度振り返ってみてください。今、通して読むと意外にすらすらと理解できる
かもしれませんよ!

    #include<stdio.h>

    int main(void)
    {
        int i;

        i = 1;
        while( i <= 100 ){
            printf("M.Katsube\n");

            i = i + 1;
        }

        return(0);
    }


さて、前回は「暗黙の型変換」が出てきたところで終わっていたと思います。
今回はここから解説を始めることにしましょう!

    ・Code15
      http://www.ichikoro.com/webp/back_list/?cd=00015

    ・Code25(前回)
      http://www.ichikoro.com/webp/back_list/?cd=00025



━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
  02.Guide  「暗黙の型変換:なぜこんなことが起きるの?」
──────────────────────────────────────

まずは、このプログラムを実行してみてください。

    #include<stdio.h>
    
    int main()
    {
        int a = 1.5;        /*初期化*/
    
        /* 変数aの値を表示 */
        printf("a = %d", a);
    
        return(0);
    }

特に意識して考えなければ、この結果は

    C:\>bcc32 sample.c
    C:\>sample
    a = 1.5

という物を想像してしまいますが、実際には下記のようになってしまいます。

    C:\>bcc32 sample.c
    Borland C++ 5.5.1 for Win32 Copyright (c) 1993, 2000 Borland
    sample.c:
    Turbo Incremental Link 5.00 Copyright (c) 1997, 2000 Borland
    
    C:\>sample
    a = 1

おっと小数点以下が切り落とされてしまいました。

なぜこのようなことが起きたのでしょうか?
ここはゆっくりと、順序だてて考えるてみましょう。


━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
  03.Guide  「暗黙の型変換:C言語には型がある」
──────────────────────────────────────

C言語では、変数に「型」という考えた方があるというのは、以前変数を解説した際
に、軽くお話したと思います。


>C言語にはint以外にも下のような型があります。
>
>    short   主に整数を扱う。
>    int     主に整数を扱う標準的な型。環境によって大きさが異なる。
>    long    shortより大きな整数を扱う。
>    char    主に文字を扱う。
>    float   小数点を扱うときに使用。
>    double  floatより桁数の多い小数点を扱うときに使用。

             Code019:しっかり基礎を固めようシリーズ 変数編 より抜粋
             http://www.ichikoro.com/webp/back_list/?cd=00019


そうなのです、int型は「主に整数を扱う」型なのです。
int以外にも、

    ・short型
    ・long型

は整数を扱う型になります。


ではもし「整数を扱う型」に対して「小数点を持った数値」が来た場合どうなってし
まうのでしょうか?そうなのです。ここで、前回お話した「暗黙の型変換」が登場す
るのです。


━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
  04.Guide  「暗黙の型変換:型には大きさがある」
──────────────────────────────────────

「暗黙の型変換」とは読んで字のごとく、「自動的に型を変換する」ということです。
これはC言語のルールとして定められているものです。

    int型の変数 = double型の値

という代入が行われた場合、

    「整数部のみの代入」

となり、小数点以下は切り捨てられます。
冷静に考えてみると、もっともな話だと思います。


と、ここで話は終わりません。
Code19では、「変数には型がある」ということ以外に、

>全ての変数には「型」という考え方があります。この型によって、メモリ上に取られ
>る大きさが変わってくるのです。つまり変数に代入する事のできる値の大きさが変わ
>るのです。
                        Code019:しっかり基礎を固めようシリーズ 変数編 より抜粋
                              http://www.ichikoro.com/webp/back_list/?cd=00019

ともご説明しました。
実際に筆者の環境で、それぞれの変数の型がどれくらいの大きさを持つか試したところ、
下記のような結果が出ました。

>    short  2 byte
>    int    4 byte
>    long   4 byte
>    char   1 byte
>    float  4 byte
>    double 8 byte

この結果から、ある一つの問題が浮かび上がります。
お分かりですね?「同じ整数を扱う型でも大きさが違う」のです。


━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
  05.Guide  「暗黙の型変換:大きな器に小さな値」
──────────────────────────────────────

では、具体的にどういったことになってしまうのでしょうか?
基本的には代入する先の変数の型に変換されます。これまで出てきた例で言うなら、

    int a = 1.5;

1.5という値が、代入する先の変数aの型、つまりint型に変換されます。


ではshort型(2byte)の値をint型(4byte)に代入する際、どういったことが起こるの
でしょうか?こういった小さな器から、そのまま大きな器に変換される場合、特に
問題はありません。

    /*
     * 「int型 = short型」の代入実験
     */
    #include<stdio.h>
    #include<limits.h>

    int main()
    {
        short s1 = 1;            /*普通に代入*/
        short s2 = SHRT_MAX;     /*shot型で扱える一番大きな値を代入*/
        int   i;

        /* short型の変数をint型の変数に代入 */
        i = s1;
        printf("s1 = %5d     i = %5d\n", s1, i);


        /* short型の最大値を代入した変数をint型の変数に代入 */
        i = s2;
        printf("s2 = %5d     i = %5d\n", s2, i);

        return(0);
    }

この実行結果は私の環境だと下記のようになりました。

    C:\>bcc32 sample.c
    Borland C++ 5.5.1 for Win32 Copyright (c) 1993, 2000 Borland
    sample.c:
    Turbo Incremental Link 5.00 Copyright (c) 1997, 2000 Borland

    C:\>sample
    s1 =     1     i =     1
    s2 = 32767     i = 32767

問題なく代入が行われているのが確認できます。
    ※SHRT_MAXについては後述します。


━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
  06.Guide  「暗黙の型変換:小さな器に大きな値」
──────────────────────────────────────

さてさて、上の項では、

>こういった小さな器から、そのまま大きな器に変換される場合、特に
>問題はありません。

と説明いたしました。
では、「大きな器から小さな器に移す場合」問題が起こるのでしょうか?
早速実験してみることにしましょう。

    #include<stdio.h>
    #include<limits.h>
    
    int main()
    {
        int   i1 = 1;            /*普通に代入*/
        int   i2 = INT_MAX;      /*int型で扱える一番大きな値を代入*/
        short s;        
    
        /* int型の変数をshort型の変数に代入 */
        s = i1;
        printf("i1 = %10d     s = %10d\n", i1, s);
    
    
        /* int型の最大値を代入した変数をshort型の変数に代入 */
        s = i2;
        printf("i2 = %10d     s = %10d\n", i2, s);
    
        return(0);
    }

さぁ、結果が楽しみですね。
ここで何も問題が起こらないとした場合、期待する結果は

    i1 =          1     s =          1
    i2 = 2147483647     s = 2147483647

という感じです。
私の環境だと実行結果は下記のようになりました。

    C:\>bcc32 sample.c
    Borland C++ 5.5.1 for Win32 Copyright (c) 1993, 2000 Borland
    sample.c:
    Turbo Incremental Link 5.00 Copyright (c) 1997, 2000 Borland

    C:\>sample
    i1 =          1     s =          1
    i2 = 2147483647     s =         -1

お!!
な、なんと正常に代入が行われていません。


これは、short型で扱えるbyte数を超えた(あふれた)場合、このように
意図しない結果が生まれます。ではここで言っている事が本当かどうか
確認してみましょう。

    #include<stdio.h>
    #include<limits.h>
    
    int main()
    {
        short s = SHRT_MAX;        /*short型で扱える一番大きな値を代入*/
    
        /* 普通に変数sを表示 */
        printf("s = %5d\n", s);
    
        /* 普通に変数sに+1した物を表示 */
        s = s + 1;
        printf("s = %5d\n", s);
    
        return(0);
    }

この実行結果はご覧の通りです。

    C:\>bcc32 sample.c
    Borland C++ 5.5.1 for Win32 Copyright (c) 1993, 2000 Borland
    sample.c:
    Turbo Incremental Link 5.00 Copyright (c) 1997, 2000 Borland
    
    C:\>sample
    s = 32767
    s = -32768

━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
  07.Guide  「暗黙の型変換:まとめてみましょう!」
──────────────────────────────────────

さぁ、ここまでの事をまとめてみましょう!

    (1)C言語の変数には「型」という考え方がある
    (2)型は、それぞれ扱う物が違い、扱える大きさも異なる
        short    2byte   主に整数を扱う。
        int      4byte   主に整数を扱う標準的な型。環境によって大きさが異なる。
        long     4byte   shortより大きな整数を扱う。
        char     1byte   主に文字を扱う。
        float    4byte   小数点を扱うときに使用。
        double   8byte   floatより桁数の多い小数点を扱うときに使用。

    (3)違う型同士で代入をすると「暗黙の型変換」が行われる
    (4)「暗黙の型変換」では、代入する先の変数の型に変換される
        例:
            int    = short  (intに変換)
            int    = long   (intに変換)
            int    = double (intに変換)
            long   = short  (longに変換)
            long   = int    (longに変換)
            double = int    (doubleに変換)

    (5)代入する先の型が扱える大きさよりも、代入する値が小さい場合は問題は起こらない。
        例:
            int    = short  (intに変換)     OK
            long   = short  (longに変換)    OK
            long   = int    (longに変換)    OK

    (6)代入する先の型が扱える大きさよりも、代入する値が大きい場合は問題が起こる。
        例:
            short  = int    (shortに変換)   NG
            int    = long   (intに変換)     NG
            

大丈夫でしょうか?


実はまだお話していない部分が2、3ありますが、またいずれ解説したいと
思います。


━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
  08.Guide  「次回予告」
──────────────────────────────────────

さてさて。散々今まで解説している通り、プログラムには3つの構造しかありません。
つまり、

    ・順次構造
    ・反復構造
    ・選択構造

の3つになります。


順次構造は、上から順番に実行していくという物です。
みなさんすでに日常的に使ってますよね。

反復構造は、ある条件が真の間、一定の処理を繰り返すというものです。
これについては、前回お話しましたよね。
    ・Code25(前回)
      http://www.ichikoro.com/webp/back_list/?cd=00025


残すところ、まだ解説していないのは選択構造ですね。
次回はこれを取り上げることにしましょう。


━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
  09.Question  「今週の問題」
──────────────────────────────────────

    Q. Aさんが一生のうちに手にする給料の合計を求めなさい。
       ただし以下の条件を考慮すること
         ・22歳に入社し、50歳で退職するものとする。
         ・初任給は200,000円とする。
         ・ボーナスは年2回、3ヶ月分出る。
         ・1年間に1回昇給し、現在の固定給の5%ずつ増えるものとする。
         ・税金など源泉徴収については一切考慮しないものとする。

       実行例:
            年齢:22  基本給: 210000  給料: 3600000
            年齢:23  基本給: 220500  給料: 7380000
            年齢:24  基本給: 231525  給料:11349000
                                :
                                :
                                :
            年齢:48  基本給: ???  給料:?????
            年齢:49  基本給: ???  給料:?????
            年齢:50  基本給: ???  給料:?????



━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
                           編    集    後    記
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━

最近、会社で取り留めの無いことをよく話しています。

    かつべ「分子って円運動をしているけれど、それって太陽系もそうだし銀河系
            もなんですよね。金太郎飴みたいにどこを切っても同じなんですよね。

            もしかしたら私の体の中にも地球があって、すごく小さい人たちが生
            きているかもしれないですよねー。とすると、今手をおいたところが
            地球と同じようになっていて、そこにいた人たちが今まさに消滅した
            のかもしれないですね」

    Mさん 「そうだよな。それと、時間と大きさってわかんないじゃん。
            今滅びた瞬間は、オレらにとっては一瞬だけど、もしかしたらその人
            たちにとっては何億年かもしれないんだよな」

    かつべ「あー、確かに、何を基準にするかでそれって違うんですよね」


いやー、まだ高校生だった時これを友達に話したら「理解できない」といわれて
ちょっとショックだったのですが、今回は「みんな同じ事を考えてるんだな」と
いう結論に落ち着きました。

んー、普通って何?っていう気分になりましたが、自分の考えを理解してくれる
人がいるって幸せなことかもしれないですね(^^)


ではでは、今度は月曜日にお会いしましょう(^.^)/~~~


---【相互広告】-------------------------------------------------------------
┏━┓┏━┓┏━┓┏━┓ ■メールアドレスだけの簡単応募
┃毎┃┃日┃┃懸┃┃賞┃ ■メルマガ読者限定スピードくじ
┗━┛┗━┛┗━┛┗━┛ ■独自懸賞豊富な懸賞サイト!
        懸賞情報無料一括投稿サービス開始!媒体も募集中
               http://www.mk-net.com/
-------------------------------------------------------------【相互広告】---

■Information 
 「Webプログラミングからのお知らせ」

    【相互広告募集のお知らせ】
      読者数を増やしたいメルマガ発行者さんを募集しています。お互いに一定期間(1〜
      3回程度)広告を掲載し合いませんか?詳細はご相談ください(無料)

         お問い合わせ: mm-webp@ichikoro.com

    【コラム募集のお知らせ】
      Webプログラミングでは、寄稿していただけるコラムやプログラムなどを募集して
      います。たくさんの読者の方にあなたをアピールする場にもなります。ぜひ有意義
      な情報やご意見をお送りください。

         お問い合わせ: mm-webp@ichikoro.com

■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■

                   【 Webプログラミング Code Sample 】

                    発  行 : ichikoro.com
                発行責任者 : 勝部 麻季人
                              < mailto:katsube@ichikoro.com >
                  発行部数 : 1865部(前回)
                 Webサイト : < http://www.ichikoro.com/webp/ >
            お問い合わせ先 : < mailto:mm-webp@ichikoro.com >

                            Powerd by まぐまぐ
    All Right Reserved, CopyRight(C) 2001 Webプログラミング Code Sample
■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■

コメント

コメントを入力. Wiki文法が有効です:
D​ X K᠎ P​ W