トップページ

本棚


両手で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に表示されています。更新することで広告が下部へ移動します。

メモリへのアクセスの制限事項の一つに、「アラインメント」もしくは「WORD境界」というものがある。

これは何かというと、奇数番地のアドレスに対して2バイト以上の型(8bit環境以外でのintなど)でアクセスすることができないという制限だ。

もちろん、すべてのCPUがその制限を持っているわけではない。幸いなことに?われらがPentiumは奇数番地アクセスが可能(たしか)。

具体的に言うと、
unsigned char* ucpHoge[100];  /*100バイトの領域確保*/
unsigned short int usiPiyo;  /*short型の変数に*/
usiPiyo = *(unsigned short int*)(ucpHoge + 1);
          /* 奇数番地のアドレスを   */
          /* short*にキャストして  */
          /* その値をとろうとしている */
          /*  ちょっとややこしい?  */

なんていうアクセスしちゃうとCPU例外が発生したりする。

この問題のいやらしい点は、ロジック上(ソースコード上)ではなかなか発見できないことである。

上の例などではまあすぐにわかるんだけど、問題は可変長のデータを扱っているとき。

実にいやらしいことに、データが可変長なので上のような処理が入っていたとしても上手くいくときと上手くいかない時がある。

なので、単体テストどころか結合テストまですり抜けて、割と後になってデバッガやらLOGやらで散々調べまくってやっと不具合の原因が判明したりする。


じゃあどうすんだよ、というと、データが可変長な場合はWork用の領域なり目的の変数なりにmemcpy。上の例だと最期の式を

memcpy(&usiPiyo, ucpHoge + 1, 
  sizeof(unsigned short int));

としてやればusiPiyoに目的の値が入るはず。

また、構造体を定義する際にもアラインメントを考慮する必要がある。

以下のような構造体定義があったとする。
typedef struct {
  char cAAA;
  int iBBB;
  char cCCC;
} ST_TEST1;

typedef struct {
  char cAAA;
  char cCCC;
  int iBBB;
} ST_TEST2;

それぞれのサイズはおそらく、(intが4バイトとして)ST_TEST1が7バイト、ST_TEST2が6バイトとなる。
コンパイラが最適化して、アクセスしやすいように(制限のあるCPUではアクセスできるように)それぞれの要素を偶数番地からに置き換えてくれるためである。つまりST_TEST1のcAAAとcBBBの間にはムダな1バイトが入ってしまう。

VC++なんかだと32bitアクセスしやすいように4バイトごとの境界に丸めようとするので、さらに構造体のサイズは変わってくるかもしれない。
(昔のMS-Cなんかだと、#pragma pack(1)だったかな?でそろえないように指定できたけど今はどうなんでしょう??)


上記の二つのアラインメントのお話は、当然ながらコンパイラおよびCPUに依存する。したがって、ある程度それらを意識して回避または吸収できるコードを書かないとプログラムの移植性はどんどん低くなってしまう。


やっぱり、C言語ってポータブルじゃないよなぁ。。




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