構造体のビットフィールドで確保される順番は

フォーラム(掲示板)ルール
フォーラム(掲示板)ルールはこちら  ※コードを貼り付ける場合は [code][/code] で囲って下さい。詳しくはこちら
non

構造体のビットフィールドで確保される順番は

#1

投稿記事 by non » 17年前

構造体のビットフィールドでメモリがどのように確保されるのか調べているのですが、
次のプログラムの場合、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;
}

GPGA

Re:構造体のビットフィールドで確保される順番は

#2

投稿記事 by GPGA » 17年前

ビットフィールドのビットの割り振りは、ほとんどの場合、環境依存になります。

non

Re:構造体のビットフィールドで確保される順番は

#3

投稿記事 by non » 17年前

回答ありがとうございます。やっぱり、コンパイラ依存ですか。
しょうがないですね。

組木紙織

Re:構造体のビットフィールドで確保される順番は

#4

投稿記事 by 組木紙織 » 17年前

>ビットフィールドのビットの割り振りは、ほとんどの場合、環境依存になります

確かに、構造体(共用体)の中身は、環境依存の部分が多いですが、
環境依存の部分は、アライメントに関する部分だけだったような記憶があります。
構造体(共用体)の中身の順番はソースコードの順番であったように思います。
今回の質問はエンディアンに関するものだと思います。

non

Re:構造体のビットフィールドで確保される順番は

#5

投稿記事 by non » 17年前

レスありがとうございます。
エンディアンということはCPUに依存するということでしょうか?
エンディアンは8ビット単位の配置ではないのですか?
いまいち意味が理解できませんので、もう少しわかるようにご説明願えますか。

GPGA

Re:構造体のビットフィールドで確保される順番は

#6

投稿記事 by GPGA » 17年前

JIS X3010:2003 6.7.2.1 構造体指定子及び共用体指定子からの引用
>構造体オブジェクト内では, 非ビットフィールドメンバ及びビットフィールドが置かれる単位は, 宣言された順に
>増加するアドレスをもつ。構造体オブジェクトへのポインタは, 適切に変換すれば, その先頭メンバ(又はビット
>フィールドならば, それが置かれた単位)を指す。さらに, その逆も成り立つ。構造体オブジェクトの中に名前の
>ない詰め物があってもよいが, 先頭には名前のない詰め物があってはならない。

以上が仕様となっています。
置かれる順番は、宣言した順番となっていますが
ビット配置はその環境のビットオーダーに依存するはずです。

toyo

Re:構造体のビットフィールドで確保される順番は

#7

投稿記事 by toyo » 17年前

エンディアンについてですが
CPUでデータバスが32本(d0-d31)あるとします
これをint(32bits)に読み込むときにd0が最上位ビットになるか最下位ビットになるかがエンディアンの違いだと理解しています。
(つまりエンディアンはビット単位)

組木紙織

Re:構造体のビットフィールドで確保される順番は

#8

投稿記事 by 組木紙織 » 17年前

共用体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
└─┴─┴─┴─┴─┴─┴─┴─┘
とはいるということです、
#そういえばエンディアンは規格で決まってなかったような気がする。→どっちみち環境依存。ですか。

non

Re:構造体のビットフィールドで確保される順番は

#9

投稿記事 by non » 17年前

たくさんの方からの回答を感謝いたします。
エンディアンがビット単位で依存するとは知りませんでした。
偶数バイトのときバイト単位で上下バイトがひっくりかえるものだと思っていました。
ありがとうございました。
最初に載せたサンプルはH8CPUのヘッダーファイルから取ってきたものですからビッグエンデアンで
実行したパソコンはXeonですからリトルエンディアンということでしょうね。

GPGA

Re:構造体のビットフィールドで確保される順番は

#10

投稿記事 by GPGA » 17年前

エンディアンはバイト単位とビット単位の両方が存在します。
バイトがビッグエンディアンであるからといって、ビットがビッグエンディアンで
あるという保障はどこにもありません。

non

Re:構造体のビットフィールドで確保される順番は

#11

投稿記事 by non » 17年前

あらま、そうなんですか。わかりにくいですね。

ibis

Re:構造体のビットフィールドで確保される順番は

#12

投稿記事 by ibis » 17年前

IntelのCPU(CeleronやPentium、つまり典型的なWindowsの環境)では、バイトがリトル、ビットがビッグですよ。
32bit整数の1は、
[[00000001] [00000000] [00000000] [00000000]]
32bit整数の256は、
[[00000000] [00000001] [00000000] [00000000]]
というように。

Hermit

Re:構造体のビットフィールドで確保される順番は

#13

投稿記事 by Hermit » 17年前

現状では、ビッグエンディアンも、リトルエンディアンも、
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;

ビットフィールドのどちら側を上に書くかという違いがあるだけだと思います。

GPGA

Re:構造体のビットフィールドで確保される順番は

#14

投稿記事 by GPGA » 17年前

>Hermitさん

いえ、ですからバイトオーダーとビットオーダーは環境によって違うんです。
通常、リトルエンディアン、ビッグエンディアンというのはバイトオーダーのことを
指します。ビットフィールド自体が滅多に使用されないので、話題に上がりにくいですが
ビットフィールドはその環境のビットオーダーにかかわってきますので
通常のリトルエンディアンやビッグエンディアンとは扱いが異なるわけです。

たかぎ

Re:構造体のビットフィールドで確保される順番は

#15

投稿記事 by たかぎ » 17年前

ビットオーダーのことは、エンディアン(あるいはエンディアンネス)とはいいませんね。
また、すでに回答が出ているように、バイトオーダーがどうであろうと、ビットオーダーには直接関係ありません。処理系によっては、コンパイルオプションによって、ビットオーダーを変えられるものもあります。

ところで、C++では問題ありませんが、Cではビットフィールドにunsigned charを使えるかどうかは処理系に依存します。また、異なる型のビットフィールドが混在した場合、多くの処理系では同じ型のビットフィールドどうしを集めて配置するようになっています。

ビットフィールドについては、以前ブログで書いたことがあるので紹介しておきます。
http://portable-c.jugem.jp/?eid=8

Hermit

Re:構造体のビットフィールドで確保される順番は

#16

投稿記事 by Hermit » 17年前

ちょっと書き方がいい加減でしたね(^^;
Borland C++ Compiler 5.5 では、
ビットフィールドは、
unsigned char B0:1;
から書いた方がいいですよ。
最初に
unsigned char B7:1;
から書いたので、おかしくなるんです。

このあたりは、他の人が多く書いていますが、環境依存なので、環境に合わせて書く必要があります。
リトルエンディアンの8086系のコンパイラは、256 などは2byte目に 1 が来るので、
> 非ビットフィールドメンバ及びビットフィールドが置かれる単位は, 宣言された順に 増加するアドレスをもつ。
を満足する為には、その方が自然なのでそういう仕様になってるだけでしょう。

閉鎖

“C言語何でも質問掲示板” へ戻る