ページ 1 / 1
構造体のビットフィールドで確保される順番は
Posted: 2008年4月30日(水) 10:44
by non
構造体のビットフィールドでメモリがどのように確保されるのか調べているのですが、
次のプログラムの場合、B7が上位B0が下位になると思っていたのですが、実行してみると
01001000になっています。コンパイラによるのでしょうか?
使用したのは、フリーのBorland C++ Compiler 5.5です。
#include<stdio.h>
struct st_p1 { // struct P1
unsigned char DDR; // P1DDR
char wk; //
union { // P1DR
unsigned char BYTE; // Byte Access
struct { // Bit Access
unsigned char B7:1; // Bit 7
unsigned char B6:1; // Bit 6
unsigned char B5:1; // Bit 5
unsigned char B4:1; // Bit 4
unsigned char B3:1; // Bit 3
unsigned char B2:1; // Bit 2
unsigned char B1:1; // Bit 1
unsigned char B0:1; // Bit 0
} BIT; //
} DR; //
};
main()
{
struct st_p1 P1;
P1.DR.BYTE=0x12;
printf("%x",P1.DR.BIT.B7);
printf("%x",P1.DR.BIT.B6);
printf("%x",P1.DR.BIT.B5);
printf("%x",P1.DR.BIT.B4);
printf("%x",P1.DR.BIT.B3);
printf("%x",P1.DR.BIT.B2);
printf("%x",P1.DR.BIT.B1);
printf("%x",P1.DR.BIT.B0);
return;
}
Re:構造体のビットフィールドで確保される順番は
Posted: 2008年4月30日(水) 10:48
by GPGA
ビットフィールドのビットの割り振りは、ほとんどの場合、環境依存になります。
Re:構造体のビットフィールドで確保される順番は
Posted: 2008年4月30日(水) 11:00
by non
回答ありがとうございます。やっぱり、コンパイラ依存ですか。
しょうがないですね。
Re:構造体のビットフィールドで確保される順番は
Posted: 2008年4月30日(水) 11:20
by 組木紙織
>ビットフィールドのビットの割り振りは、ほとんどの場合、環境依存になります
確かに、構造体(共用体)の中身は、環境依存の部分が多いですが、
環境依存の部分は、アライメントに関する部分だけだったような記憶があります。
構造体(共用体)の中身の順番はソースコードの順番であったように思います。
今回の質問はエンディアンに関するものだと思います。
Re:構造体のビットフィールドで確保される順番は
Posted: 2008年4月30日(水) 11:49
by non
レスありがとうございます。
エンディアンということはCPUに依存するということでしょうか?
エンディアンは8ビット単位の配置ではないのですか?
いまいち意味が理解できませんので、もう少しわかるようにご説明願えますか。
Re:構造体のビットフィールドで確保される順番は
Posted: 2008年4月30日(水) 12:03
by GPGA
JIS X3010:2003 6.7.2.1 構造体指定子及び共用体指定子からの引用
>構造体オブジェクト内では, 非ビットフィールドメンバ及びビットフィールドが置かれる単位は, 宣言された順に
>増加するアドレスをもつ。構造体オブジェクトへのポインタは, 適切に変換すれば, その先頭メンバ(又はビット
>フィールドならば, それが置かれた単位)を指す。さらに, その逆も成り立つ。構造体オブジェクトの中に名前の
>ない詰め物があってもよいが, 先頭には名前のない詰め物があってはならない。
以上が仕様となっています。
置かれる順番は、宣言した順番となっていますが
ビット配置はその環境のビットオーダーに依存するはずです。
Re:構造体のビットフィールドで確保される順番は
Posted: 2008年4月30日(水) 12:04
by toyo
エンディアンについてですが
CPUでデータバスが32本(d0-d31)あるとします
これをint(32bits)に読み込むときにd0が最上位ビットになるか最下位ビットになるかがエンディアンの違いだと理解しています。
(つまりエンディアンはビット単位)
Re:構造体のビットフィールドで確保される順番は
Posted: 2008年4月30日(水) 12:08
by 組木紙織
共用体DRの中身は
下のようになっているとします。
(この例は適当です)
上位 下位
┌─┬─┬─┬─┬─┬─┬─┬─┐
│B7│B6│B5│B4│B3│B2│B1│B0│
├─┼─┼─┼─┼─┼─┼─┼─┤
│ │ │ │ │ │ │ │ │BYTE
└─┴─┴─┴─┴─┴─┴─┴─┘
もしビックエンディアンなら0x12は
上位 下位
┌─┬─┬─┬─┬─┬─┬─┬─┐
│B7│B6│B5│B4│B3│B2│B1│B0│
├─┼─┼─┼─┼─┼─┼─┼─┤
│0│0│0│1│0│0│1│0│BYTE
└─┴─┴─┴─┴─┴─┴─┴─┘
もしリトルエンディアンなら0x12は
下位側から入るので
上位 下位
┌─┬─┬─┬─┬─┬─┬─┬─┐
│B7│B6│B5│B4│B3│B2│B1│B0│
├─┼─┼─┼─┼─┼─┼─┼─┤
│0│1│0│0│1│0│0│0│BYTE
└─┴─┴─┴─┴─┴─┴─┴─┘
とはいるということです、
#そういえばエンディアンは規格で決まってなかったような気がする。→どっちみち環境依存。ですか。
Re:構造体のビットフィールドで確保される順番は
Posted: 2008年4月30日(水) 12:31
by non
たくさんの方からの回答を感謝いたします。
エンディアンがビット単位で依存するとは知りませんでした。
偶数バイトのときバイト単位で上下バイトがひっくりかえるものだと思っていました。
ありがとうございました。
最初に載せたサンプルはH8CPUのヘッダーファイルから取ってきたものですからビッグエンデアンで
実行したパソコンはXeonですからリトルエンディアンということでしょうね。
Re:構造体のビットフィールドで確保される順番は
Posted: 2008年4月30日(水) 12:50
by GPGA
エンディアンはバイト単位とビット単位の両方が存在します。
バイトがビッグエンディアンであるからといって、ビットがビッグエンディアンで
あるという保障はどこにもありません。
Re:構造体のビットフィールドで確保される順番は
Posted: 2008年4月30日(水) 12:56
by non
あらま、そうなんですか。わかりにくいですね。
Re:構造体のビットフィールドで確保される順番は
Posted: 2008年4月30日(水) 18:17
by ibis
IntelのCPU(CeleronやPentium、つまり典型的なWindowsの環境)では、バイトがリトル、ビットがビッグですよ。
32bit整数の1は、
[[00000001] [00000000] [00000000] [00000000]]
32bit整数の256は、
[[00000000] [00000001] [00000000] [00000000]]
というように。
Re:構造体のビットフィールドで確保される順番は
Posted: 2008年4月30日(水) 21:44
by Hermit
現状では、ビッグエンディアンも、リトルエンディアンも、
1byteの情報は同じだと思いますが。
これが、2byte以上になると変わってきます。
char w[2] = {1,0};
これを、2byte (int *) としてみると、
ビッグだと、256
リトルだと、1
char w[2] = {0,1};
これを、2byte (int *) としてみると、
ビッグだと、1
リトルだと、256
1 を、16Bit int のビットフィールドで表すと、
ビッグが
struct {
unsigned int B15:1;
unsigned int B14:1;
unsigned int B13:1;
unsigned int B12:1;
unsigned int B11:1;
unsigned int B10:1;
unsigned int B9:1;
unsigned int B8:1;
unsigned int B7:1;
unsigned int B6:1;
unsigned int B5:1;
unsigned int B4:1;
unsigned int B3:1;
unsigned int B2:1;
unsigned int B1:1;
unsigned int B0:1; // ビッグはここが 1 になる、他は 0
} BIT;
リトルで 1 は、
struct {
unsigned int B0:1; // リトルはここが 1 になる、他は 0
unsigned int B1:1;
unsigned int B2:1;
unsigned int B3:1;
unsigned int B4:1;
unsigned int B5:1;
unsigned int B6:1;
unsigned int B7:1;
unsigned int B8:1;
unsigned int B9:1;
unsigned int B10:1;
unsigned int B11:1;
unsigned int B12:1;
unsigned int B13:1;
unsigned int B14:1;
unsigned int B15:1;
} BIT;
ビットフィールドのどちら側を上に書くかという違いがあるだけだと思います。
Re:構造体のビットフィールドで確保される順番は
Posted: 2008年5月01日(木) 01:29
by GPGA
>Hermitさん
いえ、ですからバイトオーダーとビットオーダーは環境によって違うんです。
通常、リトルエンディアン、ビッグエンディアンというのはバイトオーダーのことを
指します。ビットフィールド自体が滅多に使用されないので、話題に上がりにくいですが
ビットフィールドはその環境のビットオーダーにかかわってきますので
通常のリトルエンディアンやビッグエンディアンとは扱いが異なるわけです。
Re:構造体のビットフィールドで確保される順番は
Posted: 2008年5月01日(木) 10:15
by たかぎ
ビットオーダーのことは、エンディアン(あるいはエンディアンネス)とはいいませんね。
また、すでに回答が出ているように、バイトオーダーがどうであろうと、ビットオーダーには直接関係ありません。処理系によっては、コンパイルオプションによって、ビットオーダーを変えられるものもあります。
ところで、C++では問題ありませんが、Cではビットフィールドにunsigned charを使えるかどうかは処理系に依存します。また、異なる型のビットフィールドが混在した場合、多くの処理系では同じ型のビットフィールドどうしを集めて配置するようになっています。
ビットフィールドについては、以前ブログで書いたことがあるので紹介しておきます。
http://portable-c.jugem.jp/?eid=8
Re:構造体のビットフィールドで確保される順番は
Posted: 2008年5月01日(木) 20:11
by Hermit
ちょっと書き方がいい加減でしたね(^^;
Borland C++ Compiler 5.5 では、
ビットフィールドは、
unsigned char B0:1;
から書いた方がいいですよ。
最初に
unsigned char B7:1;
から書いたので、おかしくなるんです。
このあたりは、他の人が多く書いていますが、環境依存なので、環境に合わせて書く必要があります。
リトルエンディアンの8086系のコンパイラは、256 などは2byte目に 1 が来るので、
> 非ビットフィールドメンバ及びビットフィールドが置かれる単位は, 宣言された順に 増加するアドレスをもつ。
を満足する為には、その方が自然なのでそういう仕様になってるだけでしょう。