• 締切済み

配列から構造体へデータコピー

配列から構造体へデータのコピーをしたいのですが、 構造体のメンバがビットフィールドで構成されている時の処理がわかりません。 --------test.c----------- #include <stdio.h> #include <string.h> typedef struct{ unsigned char aaa :1; unsigned char bbb :1; unsigned char ccc :1; unsigned int ddd :13; unsigned char eee :2; unsigned char fff :2; unsigned char ggg :4; }test_t; int main(void) { test_t test_t; unsigned char data[]={0x5F, 0xFE, 0x1C}; memcpy(&test_t, data, 4); printf("aaa = %X\n", test_t.aaa); printf("bbb = %X\n", test_t.bbb); printf("ccc = %X\n", test_t.ccc); printf("ddd = %d\n", test_t.ddd); printf("eee = %X\n", test_t.eee); printf("fff = %X\n", test_t.fff); printf("ggg = %X\n", test_t.ggg); return 0; } ------期待出力--------- aaa = 0 bbb = 1 ccc = 0 ddd = 1FFE eee = 0 fff = 1 ggg = 12 「test.c」を実行した時に「期待出力」のような出力を期待していたのですが、実際には aaa = 1 bbb = 1 ccc = 1 ddd = 1 eee = 0 fff = 0 ggg = 0 と表示されてしまいます。 ビットフィールドで構成された構造体に、配列の値をそのままあてる事は出来ないのでしょうか? 出来るだけ、マスクやシフト演算を使用しないで、配列からビット単位で値を抽出したいのですが・・・

みんなの回答

  • Tacosan
  • ベストアンサー率23% (3656/15482)
回答No.4

「data は 3バイトしかないのに memcpy で 4バイト目にアクセスしてる」って問題もあるんだけど.... そもそもビットフィールドを使った時点で「処理系依存」の嵐です: ・_Bool と (signed/unsigned) int 以外の型が使えるかどうかは処理系定義 ・ビットをどの順に割り当てるかは処理系定義 ・当該ビットフィールドをすべて入れることができれば, どのような記憶単位を割り当ててもいい (そのアラインメントは指定しない) ・ビットフィールドを順に詰めていって余裕がなくなったときに「とりあえず入るところだけ入れて後は別の記憶単位にする」か「詰めるのをあきらめて新しい記憶単位にする」かは処理系定義 つまり, sizeof(test_t) は 3~12 まで考えられます. ま, 「11」とかになることはないけど. さらに, エンディアンの問題も発生するのでこのような方法は十分に処理系を理解し, かつ「その処理系と心中する」意気込みがなければ避けるべきでしょう.

  • titokani
  • ベストアンサー率19% (341/1726)
回答No.3

>出来るだけ、マスクやシフト演算を使用しないで、配列からビット単位で値を抽出したいのですが・・・ ビットフィールドを使ったとしても、結局のところコンパイラが代わりにマスクやシフト演算をするコードを出力するだけなので、できあがるプログラムはそんなに変わらないですよ。 ビットの並びとかを思うように制御したいのなら、ビットフィールドは使わずにマスクやシフトを使うほうが確実です。マクロやインライン関数などをうまく使えば、実行効率もほとんど問題ないはずです。

  • buriburi3
  • ベストアンサー率44% (353/792)
回答No.2

処理系依存ですのでマクロを組むか事前に条件を確認する必要があります。 1)パディングサイズ 2)ビィットフィールドの並び(LMBから並ぶのかHMBから並ぶのか) aaaがバイトフィールトの1ビット目に取られるのか8ビット目にとられるのか。 ちなみにMaicroSoftのCコンパイラでx86プラットフォームの場合は0ビット目に取られます。 質問の期待値を得るには::パディングサイズ1でx86系の場合:: unsigned char data[]={0x03,0xFE,0x1F,0xC4};になると思います。 ※MS-Cでは13ビットにするとintじゃなくてshort intになるみたいです。 ざっくり、こんなコード書けば簡単に確認できます。 パディングサイズはコンパイルオプションでも変わるので決めておかないと困ったことになります。 #include <stdio.h> #include <string.h> #include <stdlib.h> typedef struct{ unsigned char aaa :1; unsigned char bbb :1; unsigned char ccc :1; unsigned int ddd :13; unsigned char eee :2; unsigned char fff :2; unsigned char ggg :4; }test_t; int main( ) { int n,l ; unsigned char *data ; test_t *test ; n = sizeof(test_t) ; printf("sizeof(test_t) = %d\n",n) ; data = malloc(n) ; memset(data,0,n) ; test = (test_t *)data ; test->aaa = 1 ; test->eee = 3 ; for (l=0;l<n;l++) { printf("%02d: %X\n",l,data[l]) ; } }

noname#80090
noname#80090
回答No.1

ビットフィールドでデーターを詰めたい場合、型をむやみに変えてはいけません。 (通常の構造体でも同じようなことは言えますがパディングが起こります) あと、ビッグエンディアンの配置を期待されているようですが 実行結果でみると、リトルエンディアンのようです。 配置の取り方を変えましょう。 以下サンプル(期待出力が意味不明だったので %d の位置を変更しました) #include <stdio.h> #include <string.h> typedef struct { unsigned aaa:1; unsigned bbb:1; unsigned ccc:1; unsigned ddd:13; unsigned eee:2; unsigned fff:2; unsigned ggg:4; } test_t; int main (void) { test_t test_t; unsigned data[] = {0x00c4fff2}; memcpy (&test_t, data, sizeof data); printf ("aaa = %X\n", test_t.aaa); printf ("bbb = %X\n", test_t.bbb); printf ("ccc = %X\n", test_t.ccc); printf ("ddd = %X\n", test_t.ddd); printf ("eee = %X\n", test_t.eee); printf ("fff = %X\n", test_t.fff); printf ("ggg = %d\n", test_t.ggg); return 0; }

関連するQ&A

  • 配列の移動

    TEXTファイルに文字列を書き込んだり削除したり移動したりするプログラムを作成していますが、 aaa bbb ccc ddd eee fff ggg hhh iii このような内容を 1,aaa bbb ccc 2,ddd eee fff 3,ggg hhh iii のように上から順番に配列化して番号を指定して移動させたいのですが、 3の配列を2の上(配列1と配列2の間)や下(配列2と配列3の間)に移動するのにはどのようにしたら良いのでしょうか?

    • ベストアンサー
    • Perl
  • C言語による「テキストファイルの読み書き(fprintf)」について

    C言語による「テキストファイルの読み書き(fprintf)」について質問です ずぶの初心者ですが、既知のファイルの1行目に指定した文字列を付加させるプログラムを作りたいと思っています。 以下のように作りました。 ------------------------------------------------------------ #include <stdio.h> int main(void) { FILE *fp; fp = fopen("test.csv","r+"); fprintf(fp,"コントロールカラム1,コントロールカラム2,・・・(略)・・・,コントロールカラム56\n"); fclose(fp); return 0; } ------------------------------------------------------------ このとき「test.csv」の内容が以下のようであったとします。(容量は1MBくらいです。) 001,aaa,bbb,ccc,ddd,eee,fff,ggg,hhh,iii,jjj 002,aaa,bbb,ccc,ddd,eee,fff,ggg,hhh,iii,jjj ~(略) 5000,aaa,bbb,ccc,ddd,eee,fff,ggg,hhh,iii,jjj この状態でプログラムをコンパイルして実行すると、「test.csv」の内容が以下のようになってしまいます。(一行目が消える) AAA,BBB,CCC,DDD,EEE 002,aaa,bbb,ccc,ddd,eee,fff,ggg,hhh,iii,jjj ~(略) 5000,aaa,bbb,ccc,ddd,eee,fff,ggg,hhh,iii,jjj またcsvの行が増える度に妙な挙動になっていきます・・・(一行あいたり、先頭行が5行ほど消えたり) 希望する動作としては コントロールカラム1,コントロールカラム2,・・・(略)・・・,コントロールカラム56 001,aaa,bbb,ccc,ddd,eee,fff,ggg,hhh,iii,jjj 002,aaa,bbb,ccc,ddd,eee,fff,ggg,hhh,iii,jjj ~(略) 5000,aaa,bbb,ccc,ddd,eee,fff,ggg,hhh,iii,jjj のようになるようにしたいのですがどのようにすればよいのでしょうか。 よろしくお願いします。 (使用ソフト:Borland C++ Compiler, Cpad) 参考にしたサイトの項目:http://homepage3.nifty.com/mmgames/c_guide/17-01.html

  • 配列の変換

    配列の中身を変換したいのですが、どうコーディングするのが一般的でしょうか。 以下を、 char Test1[]= "aaa\n"         "bbb\n"         "ccc\n"         "ddd\n"; ↓このように直す。またこれを上↑の書式へ変換する。 char *Test2[] = {    "aaa",    "bbb",    "ccc",    "ddd",    NULL }; malloc() 関数を使うと思うのですが・・・ 変換のサンプル集みたいのがあれば教えていただきたいです。

  • 構造体の宣言について

    今解析しているC言語のプログラムで以下の様な構造体の宣言があります。 typedef struct { unsigned char :3; unsigned char aaa :1; unsigned char bbb :1; unsigned char ccc :1; unsigned char ddd :1; unsigned char eee :1; } tTSR ; :3や:1の部分の意味がわかりません。 御存知の方ご回答よろしくお願いします。

  • CSVデータをツリー表示させたい

    業務で、WEBサイトにCSVデータを表示させたいと考えています。 CSVデータは、毎日更新されるもので、行数も日々変更されます。 項目の中に「レベル」という項目があり、この「レベル」の値を使って、 ツリー表示出来ないかと考えています。 希望としては、決められたフォルダに決められたファイル名で、 CSVデータを置けば、自動的にWEB上にツリー表示されるという ことです。 J-query等で、これを実現出来るプラグインが無いか探しているのですが、 なかなか希望に合うものが見つからず、困っています。 (CSVをWEB表示するものは見つかるのですが、ツリー表示出来る ものが見つかりません) 何か、良い方法があれば、ご教示頂けませんでしょうか? 例 コード  レベル 品名  規格 ・・・・    コード     レベル 品名  規格 ・・・・  1234    1   AAA   aaa       -1234       1    AAA   aaa 2345    2   BBB   bbb        ∟2345     2    BBB  bbb 3456    3   CCC   ccc          ∟3456   3    CCC  ccc 4567    3   DDD   ddd          ∟4567   3    DDD  ddd 5678    3   EEE   eee           ∟5678   3    EEE  eee 6789    4   FFF   fff             ∟6789  4    FFF   fff 7890    3   GGG  ggg           ∟7890   3    GGG  ggg

  • sedで文字列の抜き出し

    ある一部分の文字列を抜き出したく、sedを使用したいと思って試行錯誤しております。 ↓あるファイル内の文字列 aaa bbb=ccc:ddd=eee:fff=ggg: aaa bbb=hhh:ddd=iii:fff=jjj: ※aaaとbbbの間はスペースです。 ※bbb,ddd,fffはある一定のキーワードです。 ※ccc,eee,ggg,hhh,iii,jjjはバラバラの文字列で長さも一定ではありません。 【質問】 上記の文字列の中でddd=の後の文字列(eee,iii)のみを抜き出したいです。 以下のようなsedを試してみましたが、 eee:fff=ggg iii:fff=jjj が抜き出されてしまいます。 sed 's/.*:ddd=\(.*\):\(.*\)$/\1/' 恐れ入りますが、皆様の知恵をお貸し下さい。

  • ArrayListに多次元配列

    ArrayListに多次元配列の変数を格納したのですが、取り出し方がわからず困っています。 ----------------------------------------------- String[][] str = {{"aaa","bbb","ccc","ddd","eee","fff"}, {"aaa","bbb","ccc","ddd","eee","fff"}, }}; ArrayList array = new ArrayList(); array.add(str[0]); array.add(str[1]); ----------------------------------------------- 上記の場合で、str[0][2];を取得する方法がわかりません。 java初心者なのでおかしな質問かもしれませんが、宜しくお願いします。

    • ベストアンサー
    • Java
  • VBAでCSV内にある改行を取る方法

    あるシステムが吐くcsvファイルの項目の中に改行が入っているものがあります。 例) 01,aaa,bbb(改行)bbb,ccc(改行) 02,ddd,eee,fff(改行) 03,ggg(改行)ggg,hhh,iii(改行) このCSVファイルをエクセルのマクロで読み込んでシートに展開したい のですが、項目中にある改行で別レコードを認識してしまいます。 結果) A B C D ---+---+---+--- 01 aaa bbb  bbb ccc 02 ddd eee fff 03 ggg ggg hhh iii これを以下のようにしたいのですが・・・ A B C D ---+------+------+---- 01 aaa bbbbbb ccc 02 ddd eee fff 03 gggggg hhh iii どうやればよいでしょうか? ご教授お願いいたします。

  • SQLについて

    aaa bbb ccc ddd eee ggg hhh ---------------------------------------------- 111 111 111 111 111 111 111 112 112 112 112 112 112 111 112 113 113 113 113 113 111 114 114 114 114 114 114 111 114 114 114 114 114 114 112 114 115 115 114 114 115 111 114 115 115 114 114 115 112 116 116 116 116 116 116 111 116 116 116 116 116 116 112 116 116 116 116 116 117 111 116 116 116 116 116 117 112 118 118 118 118 118 118 118 上記のようなデータより、SQLのSELECTを使用して、以下のように抽出したいです。 抽出条件は以下が全て満たしているものとなります。 ・aaa,ccc,ddd,eee,gggが重複、hhhが小さいもの ・bbbが異なるもの aaa bbb ccc ddd eee ggg hhh ---------------------------------------------- 112 112 112 112 112 112 111 ・・・(1) 112 113 113 113 113 113 111 ・・・(1) 114 114 114 114 114 114 111 ・・・(2) 114 115 114 114 114 115 111 ・・・(2) (1)はaaa,ccc,ddd,eee,gggが重複、bbbが異なるため抽出対象 (2)はaaa,ccc,ddd,eee,gggが重複、bbbが異なるため抽出対象  また、hhhが小さいもの 以上、よろしくお願いします。

  • Excelの関数に詳しい方、お願いします。

    わかりづらい説明かもしれませんが、よろしくお願いします。 例として、 AAA*BBB*CCC*DDD*EEE*FFF AAA*BBB*CCC*DDD*EEE*FFF AAA*BBB*CCC*DDD*EEE*FFF AAA*BBB*CCC*DDD*EEE*FFF AAA*BBB*CCC*DDD*EEE*FFF ・ ・ ・ といった文字列がエクセルの先頭列A1~A100までずらりと並んでいるとします。 各アルファベットには任意の数字(日付など)が入るとして、この並んだ百件のデータからCCCの部分の最大値を表示するための適切な関数があれば教えていただけないでしょうか? 現在少々急いでいるため言葉足らずで申し訳ありませんが、よろしくお願いいたします.