2017年03月24日
3月24日 ネットとC言語
3月24日
Q:C言語では文字も数字も一緒くたに扱われているように思えます。
初心者には紛らわしいのですが。
A:
私たちが画面で見る文字も数字も、最小情報量であるビット(0 か 1)
の組み合わせで表現されます。
例えば、ASCIIコードでは、英字の A は41h(0x41)という値で表現されます。
最も機械に近いレベルで表現すると 01000001 です。
つまり、'A'も0x41も機械内部では 01000001 であり、画面上では 英字のAです。
したがって、C言語では、変数をXとして、X='A'とするのと、X=0x41
とするのは同じことになります。
紛らわしく感じるのは、画面上の数字や文字をそのまま受け取るからです。
次のように考えると良いでしょう。
私たちは文字「A」を文字そのものとして理解していますが、コンピュータが扱う
最小情報量はビットで 0 か 1ですから、「A」そのものは認識できません。
そこで、「A」を 01000001 に当てはめ、機械で「A」という文字を処理できるよう
にしているのです。
ただし、0 と1の並びは人間にわかりにくいので、通常は16進数で表現されます。
Aは 01000001ですから、16進数で41となります。
コンピュータでの表現 画面での英数字
------------------------------------------------------------
16進数の 48 65 6C 6C 6F 英字で H e l l o
16進数の 31 32 33 34 35 数字の 1 2 3 4 5
とにかく、私たちが使う文字や数字が機械の内部ではどのように扱われているか、
ということに興味を持つことです。
--------------------------------------------------------------------------------
Q:よく「文字化けする」ということを耳にしますが、文字化けする原理を教えて下さい。
A:まず、C言語との関連で説明しましょう。
例えば、エスケープ文字は円記号('¥' ないし '\' )で、そのASCIIコードは
5Chです。
ここで、漢字の「表」を例に取ると、シフトJISでは16進数の 955C です。
もうお分かりですね。
もしコンパイラなどが 955C を漢字と認識せず、95と5Cと別々に読んでしまうと、
5Ch は '\' ですから文字として認識されません。
したがって、955Ch は 95だけとして読まれてしまい、「表」という文字はどこか
へ消えてしまいます。
古いCコンパイラ(Lattice C ver.2など)ではよくあった話です。
私もプログラミングの際に苦労しました。
現在のCコンパイラは漢字を扱えますが、注意はしておく必要があります。
私は単なる文章を書く場合やプログラミングにおいては高機能エディタの
MIFESを使っています。
16進数での入力・表示機能も備えています。
たとえば、全角スペース1個と半角スペース2個はパソコンの画面では区
別できませんが16進数表示にすると簡単に判別できます。
次に、漢字コードの関係で文字化けが生じる原因を説明しましょう。
漢字変換には、パソコンではJISコードやシフトJISコード、ワークステーションで
はEUCコードが使われます。
例えば、「大学」を例にとると、
大 学
シフトJISでは、91E5 8A77
JISでは、4267 3358
と16進数の値が異なります。このように、同一漢字でも16進数が異なることから、
漢字を認識する方法も異なるということになります。
ですから、異なる機種の間で通信する場合はコードを自動的に判別するソフトで
ないと文字化けすることがあります。
自分のパソコンがどの漢字コードを用いているか、通信の相手がどのコードを用
いているかを調べておくことも重要です。
試しに、図書館を呼び出して、図書検索をEUCコードと異なるコートでやってみて下さい。
--------------------------------------------------------------------------------
Q:マスクとはどのようなことですか。
A:例で示しましょう。
X & 0X00FF とは、数字X と 0X00FFとのビットごとのANDをとることです。
0X00FFをビットで示す(上段はビット、下段はビットフィールド)と、
0 0 0 0 0 0 0 0 1 1 1 1 1 1 1 1
---------------------------------------------------
15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0
となります。上位8ビットはゼロですから、Xと0X00FFとのANDをとった数も、
上位8ビットはゼロになります。つまり、上位8ビットはフィルターをかけ
て隠すことを意味しますので、マスクするというわけです。
その他の例
X & 0x7fff 15ビット目をマスク
X & 0x003f 6ビット目以上をマスク
X & 0x000f 4ビット目以上をマスク
(補足)
インターネットでは「サブネットマスク」が使われます。
サブネットマスクは十進数のオクテットで、
255.255.0.0
255.255.255.0
などと表されます。
10進数の255は、16進数の FF、2進数の 11111111 です。
10進数の 0 は、16進数の 00、2進数の 00000000 です。
これから、なぜ「マスク」というのか予想できますね。
--------------------------------------------------------------------------------
Q:ビットシフトとはどのようなことですか。
A:例で示しましょう。
0XFF00 >> 8 の場合、右へ8ビットシフトすると、右側の8ビットは除か
れ、代わりに左側に8ビット分 0が詰められます。
図示しますと、
1111 1111 0000 0000 ・・・・ 0XFF00
----------------------
1111 1111 ・・・・ 右の8ビット( 0000 0000)が除かれる
0000 0000 ・・・・ 左に8ビット0が詰められる
----------------------
0000 0000 1111 1111 ・・・・ 結局、0X00FF となる。
--------------------------------------------------------------------------------
Q:マスクやビットシフトはどのようなことに応用されますか。
A:例で示しましょう。
例題:構造体の中に「年月日」を示す16ビットのビットフィールド
が入っているものとします。
Borland C++ Ver3.0 の ffblk.ff_fdate を例にとっています。
ffblk.ff_fdate のビットフィールド・・・ 日:ビット 0-4
月:ビット 5-8
年:ビット 9-15
図示すると、
15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0
|------- 年 --------|---- 月 ---|---- 日 ------|
となります。
ここで、年(1980年以降の年数)をy、月(1-12)をm、日(1-31)をd、としましょう。
年を得るのは簡単ですね。
ffblk.ff_fdate を9ビット右へシフトすればよい。
(「月日」の桁を削除し、残った「年」を右へ桁下げすると考えると分かり易い)
結局
y = ffblk.ff_fdate >> 9;
日を得るのはどうですか。
ffblk.ff_fdate の 左側11ビットをマスクすればよい。
0000 0000 0001 1111 は 0X001F です。
結局、
d = ffblk.ff_fdate & 0X001F;
月を得るのは少々手強いです。
月を得るのは、マスクとビットシフトの応用問題です。
まず、5ビット右へシフトさせて、日の5ビットを捨てましょう。
すると 00000年月 が イメージとしてのビットフィールドになります。
次に、月(下位4ビット)だけ残すために、上位12ビットをマスクして隠します。
マスクするのは上位12ビットですから、
0000 0000 0000 1111 との AND をとればよい。( 0X000F との AND をとる。)
結局、
m = ( ffblk.ff_fdate >> 5 ) & 0X000F;
分かりましたか。
初級者には、ビット操作は無理かもしれません。しかし、C言語の魅力の一つはこう
いったビット単位の操作が可能なことにあるのです。
Q:C言語では文字も数字も一緒くたに扱われているように思えます。
初心者には紛らわしいのですが。
A:
私たちが画面で見る文字も数字も、最小情報量であるビット(0 か 1)
の組み合わせで表現されます。
例えば、ASCIIコードでは、英字の A は41h(0x41)という値で表現されます。
最も機械に近いレベルで表現すると 01000001 です。
つまり、'A'も0x41も機械内部では 01000001 であり、画面上では 英字のAです。
したがって、C言語では、変数をXとして、X='A'とするのと、X=0x41
とするのは同じことになります。
紛らわしく感じるのは、画面上の数字や文字をそのまま受け取るからです。
次のように考えると良いでしょう。
私たちは文字「A」を文字そのものとして理解していますが、コンピュータが扱う
最小情報量はビットで 0 か 1ですから、「A」そのものは認識できません。
そこで、「A」を 01000001 に当てはめ、機械で「A」という文字を処理できるよう
にしているのです。
ただし、0 と1の並びは人間にわかりにくいので、通常は16進数で表現されます。
Aは 01000001ですから、16進数で41となります。
コンピュータでの表現 画面での英数字
------------------------------------------------------------
16進数の 48 65 6C 6C 6F 英字で H e l l o
16進数の 31 32 33 34 35 数字の 1 2 3 4 5
とにかく、私たちが使う文字や数字が機械の内部ではどのように扱われているか、
ということに興味を持つことです。
--------------------------------------------------------------------------------
Q:よく「文字化けする」ということを耳にしますが、文字化けする原理を教えて下さい。
A:まず、C言語との関連で説明しましょう。
例えば、エスケープ文字は円記号('¥' ないし '\' )で、そのASCIIコードは
5Chです。
ここで、漢字の「表」を例に取ると、シフトJISでは16進数の 955C です。
もうお分かりですね。
もしコンパイラなどが 955C を漢字と認識せず、95と5Cと別々に読んでしまうと、
5Ch は '\' ですから文字として認識されません。
したがって、955Ch は 95だけとして読まれてしまい、「表」という文字はどこか
へ消えてしまいます。
古いCコンパイラ(Lattice C ver.2など)ではよくあった話です。
私もプログラミングの際に苦労しました。
現在のCコンパイラは漢字を扱えますが、注意はしておく必要があります。
私は単なる文章を書く場合やプログラミングにおいては高機能エディタの
MIFESを使っています。
16進数での入力・表示機能も備えています。
たとえば、全角スペース1個と半角スペース2個はパソコンの画面では区
別できませんが16進数表示にすると簡単に判別できます。
次に、漢字コードの関係で文字化けが生じる原因を説明しましょう。
漢字変換には、パソコンではJISコードやシフトJISコード、ワークステーションで
はEUCコードが使われます。
例えば、「大学」を例にとると、
大 学
シフトJISでは、91E5 8A77
JISでは、4267 3358
と16進数の値が異なります。このように、同一漢字でも16進数が異なることから、
漢字を認識する方法も異なるということになります。
ですから、異なる機種の間で通信する場合はコードを自動的に判別するソフトで
ないと文字化けすることがあります。
自分のパソコンがどの漢字コードを用いているか、通信の相手がどのコードを用
いているかを調べておくことも重要です。
試しに、図書館を呼び出して、図書検索をEUCコードと異なるコートでやってみて下さい。
--------------------------------------------------------------------------------
Q:マスクとはどのようなことですか。
A:例で示しましょう。
X & 0X00FF とは、数字X と 0X00FFとのビットごとのANDをとることです。
0X00FFをビットで示す(上段はビット、下段はビットフィールド)と、
0 0 0 0 0 0 0 0 1 1 1 1 1 1 1 1
---------------------------------------------------
15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0
となります。上位8ビットはゼロですから、Xと0X00FFとのANDをとった数も、
上位8ビットはゼロになります。つまり、上位8ビットはフィルターをかけ
て隠すことを意味しますので、マスクするというわけです。
その他の例
X & 0x7fff 15ビット目をマスク
X & 0x003f 6ビット目以上をマスク
X & 0x000f 4ビット目以上をマスク
(補足)
インターネットでは「サブネットマスク」が使われます。
サブネットマスクは十進数のオクテットで、
255.255.0.0
255.255.255.0
などと表されます。
10進数の255は、16進数の FF、2進数の 11111111 です。
10進数の 0 は、16進数の 00、2進数の 00000000 です。
これから、なぜ「マスク」というのか予想できますね。
--------------------------------------------------------------------------------
Q:ビットシフトとはどのようなことですか。
A:例で示しましょう。
0XFF00 >> 8 の場合、右へ8ビットシフトすると、右側の8ビットは除か
れ、代わりに左側に8ビット分 0が詰められます。
図示しますと、
1111 1111 0000 0000 ・・・・ 0XFF00
----------------------
1111 1111 ・・・・ 右の8ビット( 0000 0000)が除かれる
0000 0000 ・・・・ 左に8ビット0が詰められる
----------------------
0000 0000 1111 1111 ・・・・ 結局、0X00FF となる。
--------------------------------------------------------------------------------
Q:マスクやビットシフトはどのようなことに応用されますか。
A:例で示しましょう。
例題:構造体の中に「年月日」を示す16ビットのビットフィールド
が入っているものとします。
Borland C++ Ver3.0 の ffblk.ff_fdate を例にとっています。
ffblk.ff_fdate のビットフィールド・・・ 日:ビット 0-4
月:ビット 5-8
年:ビット 9-15
図示すると、
15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0
|------- 年 --------|---- 月 ---|---- 日 ------|
となります。
ここで、年(1980年以降の年数)をy、月(1-12)をm、日(1-31)をd、としましょう。
年を得るのは簡単ですね。
ffblk.ff_fdate を9ビット右へシフトすればよい。
(「月日」の桁を削除し、残った「年」を右へ桁下げすると考えると分かり易い)
結局
y = ffblk.ff_fdate >> 9;
日を得るのはどうですか。
ffblk.ff_fdate の 左側11ビットをマスクすればよい。
0000 0000 0001 1111 は 0X001F です。
結局、
d = ffblk.ff_fdate & 0X001F;
月を得るのは少々手強いです。
月を得るのは、マスクとビットシフトの応用問題です。
まず、5ビット右へシフトさせて、日の5ビットを捨てましょう。
すると 00000年月 が イメージとしてのビットフィールドになります。
次に、月(下位4ビット)だけ残すために、上位12ビットをマスクして隠します。
マスクするのは上位12ビットですから、
0000 0000 0000 1111 との AND をとればよい。( 0X000F との AND をとる。)
結局、
m = ( ffblk.ff_fdate >> 5 ) & 0X000F;
分かりましたか。
初級者には、ビット操作は無理かもしれません。しかし、C言語の魅力の一つはこう
いったビット単位の操作が可能なことにあるのです。