トップページ

本棚


両手で1000まで数えられますか?:2進法の話
数値 - 危険物取り扱い注意
100 × 200 =32?:変数のオーバーフローの話
パリティビット
小数の扱いについて
ぽいんた
ぽいんた2
ぽいんた3
ジ・オリジン
ジ・オリジン:補足
かっこつける話
かっこつける話2
文字列のこと
タイミングの話
拡張性の話
取り込む話
staticな話

コンパイルの話1
コンパイルの話2:止まらぬビルド
コンパイルの話3:マシン語に落ちるということ1:メモリの話
コンパイルの話4:マシン語に落ちるということ2:最適化
コンパイルの話5:マシン語に落ちるということ3:変数とスタック
コンパイルの話6:コンパイラはそもそも何をやってくれるのか??
リンクの話
プリプロセッサの話

OS、というもの

オブジェクト指向1
オブジェクト指向:2
オブジェクト指向:3

オブジェクト指向:番外 C言語のソースファイルの話
オブジェクト指向:番外 C言語での「再利用性」と「カプセル化」データ構造とアルゴリズム


抽象的な話

寝込んで布団の中で考えたこと
こんなの、常識??
お仕事プログラミング
ソフトでハードなプログラム
プログラムするということ
お勉強
プログラムを学ぶということの補足
C言語:「学問」と「実務」
統合開発環境
C言語ってポータブルですか?
C言語ってポータブルですか?:2
あなたは、どう読みますか?
ああ勘違い
試してガッテン
低級品
質問をするということ
ポカ
「何もしない」 != 「無駄」
エディタの話
もっと手を抜こう

いまどきの、アセンブラ

VisualStudio2005
VisualStudio2005:2

戦争の防ぎ方、に対する私の考え
身近な差別
改革
地球に優しいなんて大嘘
統計で嘘をつく方法

言葉について
言葉について:2

神が死んだということ
善悪の彼岸から、力への意思を目覚めさせるということ

本を読むということ
本を読むということ:2

絵を描く話
地図
地球儀

オカルトのお話
がんだむさん
RPGソフトウェア
記紀神話の不思議



メニュー

※上記の広告は60日以上更新のないWIKIに表示されています。更新することで広告が下部へ移動します。

変数には「型」があります。

この「型」って言うのは何なのかというと、
主に値を格納できるサイズの違いです。


C言語の場合、整数型の変数の型としては
char、int、short int、long int、long long int 
がありますね。
(実数型も入れたらdouble、floatなどもありますが)

それぞれ、1byte、2byte、4byte、8byteの領域を持っています。

1byteは8bitでした。なので、1byteで256通りの状態を表せるのでした。

ということは、
2byteなら256×256通り、
4byteなら256の4乗通り、
8byteなら256の8乗通りの状態が表せるわけです。

これは逆に言うと、ある型で表せる範囲が限定されているということでもあります。

unsigned long long intなら0~18,446,744,073,709,551,615まで表せるわけで、まあ普通の数値であれば収まるとは思いますが。

でも例えばcharの変数には1000なんて数字を表すことはできません。

これは結構、不便なことなのです。それは、

例えばunsigned charの変数ca,cbがあったとします。
この二つの変数の乗算の結果を受け取るためには、
unsigned shortの変数が必要となります。
unsigned short同士の乗算であれば、unsigned longがやはり同様に必要です。

なぜかというのはお分かりだと思います。
計算の結果が変数の表せる値の範囲におさまらないことがあるためです。

このような「変数の表せる値の範囲におさまらない」値を代入しようとした時には、はみ出した部分は捨てられてしまいます。これを「変数のオーバーフロー」といいます。

例えば、
unsigned char ca = 100, cb = 200; 
ca *= cb; 
などとするとcaには20000(0x4E20)が入って欲しいわけですが、caは1byteしかないためはみ出した部分(0x4E)が捨てられます。
なので、結果としてcaには32(0x20)が格納されるわけです。

100×200の答えが、32になってしまうわけです。恐ろしいですね。

同様に、100 + 200も300(0x012C)ではなく44(0x2C)となります。

結局、たとえlong long intを使ったとしても、表せる状態は多くなりますが限界があることには変わりません。

変数の計算(特に加算・乗算)には特に注意をしましょう。



逆に、この切り捨てられることを利用したのがチェックサムと呼ばれるデータの整合性の保障方法です。
あるデータが100byteあるとして、
unsigned char dat[100]; 
unsigned char sum; 
int i; 
・・・ 
for(i = 0; i < sizeof(dat); i++) 
{ 
  sum += dat[i]; 
} 
などとして1byteのサム(SUMとは合計のこと)をとります。
オーバーフローすることを逆手に取るわけです。

通信する際にデータの最後にこのサム値を付加してやり
受信側でも受信後同様の処理を行って、
計算したサムと受信したサム値が一致していればノイズなどがのることなく正常に受信できたと解釈できるわけです。

もちろん、1/255の確立で偶然一致することもありえます。
(例えばデータ{100,200}のチェックサムは0x2cですが、
データ{256,200}のチェックサムも0x2cとなってしまいます)

しかしながら通信におけるデータの整合性チェックは簡便かつ軽量であることも求められるので、クリティカルなデータで無い場合にはこれで十分チェックの役割を果たします。


変数の表せる範囲に限界があるということは、結構見落としがちなことで、思わぬ不具合につながることがあります。

プログラムを書いた本人は思い込みもあるので、ソースを追っていっても不具合の原因がわからず、デバッガでステップ実行していったりして始めて原因がわかるようなことにもなりかねません。

「数値」は最も基本的で、もっとも扱うことの多いデータです。だからこそ、たかが足し算、掛け算であってもプログラミングする際にはキチンと気をつけることが重要だと思います。



【おまけ】
bitを表示するデバッグ用関数。
いろいろな変数を食わせて雰囲気つかんでください。

使い方:
第一引数にデバッグ用の文字列
第二引数にbitデータのポインタ
第三引数にbitデータのサイズ(byte単位)
※以下のコードはWebできれいに見せるために
 全角スペースを含んでいます!!
void vDbgBit(char* str, unsigned char* ucp, size_t len) 
{ 
  unsigned char ucWork, i; 

  printf("[DBG]vDbgBit:%s [", str); 

  for(i = 0; i < (len * 8); i++) 
  { 
    ucWork = 0x80 >> (i % 8); 
    printf("%c", 
      ((ucp[i / 8] & ucWork) ? '1' : '0')); 
    if(!(i / 4)) 
    { 
    printf(" "); 
    } 
  } 
  printf("]\n"); 
} 




| 新しいページ | 編集 | 差分 | 編集履歴 | ページ名変更 | アップロード | 検索 | ページ一覧 | タグ | RSS | ご利用ガイド | 管理者に問合せ |
@wiki - 無料レンタルウィキサービス | プライバシーポリシー