2進数で表示された数値をビッグエンディアンで表示させる方法
解決済
回答 4
投稿
- 評価
- クリップ 1
- VIEW 2,514
こんにちは
305419896(16進数0x12345678)をバイト、ワード、ビットで表示するプログラムを作成しています。
ビットで表示する際に2進数変換後にリトルエンディアンからビッグエンディアンに変換したときbit[0]~bit[15]に不明な文字が入力されてしまいます。bit[16]以降は正常に表示されているのですが何が原因なのかわかりません。
下記コードの何が原因なのかご教授いただきたいです。
可能ならば修正コードも載せていただけると非常にありがたいです。
#define _CRT_SECURE_NO_WARNINGS//scanf警告解除
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define WORD_SIZE (2)
#define BYTE_SIZE (4)
#define BIT_SIZE (32)
typedef union
{
unsigned int data; /* 4byte */
unsigned short word[WORD_SIZE]; /* 2byte×2 */
unsigned char byte[BYTE_SIZE]; /* 1byte×4 */
unsigned char bit[BIT_SIZE]; /* 1byte×32 */
}DATA;
//変数宣言
int byte_cnt;//バイトサイズカウンタ
int bit_cnt;//ビットサイズカウンタ
//関数プロトタイプ宣言
void output_data(DATA *data);
//メイン関数
int main(int argv, char* arg[]) {
DATA init_data;//入力用データ初期化用
DATA *union_data;//入力用データ
union_data = &init_data;//ポインタ初期化
union_data->data = 305419896;
printf("入力データ:");
printf("%d\n", union_data->data);
printf("=======================================\n");
output_data(union_data);//データ出力関数呼び出し
//デバッグ用
#if 1
int debag;
scanf("%d", &debag);
#endif
return 0;
}
//データ出力関数
void output_data(DATA *data) {
DATA endian_init;//出力用データ初期化用
DATA *endian_data;//出力用データ
endian_data = &endian_init;//ポインタ初期化
/***************************/
/*データ名表示 */
/***************************/
printf("=======================================\n");
printf("DATA : 0x%08X\n", data->data);
/***************************/
/*ワード表示 */
/***************************/
printf("=======================================\n");
endian_data->word[0] = data->word[1];//エンディアン変換
endian_data->word[1] = data->word[0];//エンディアン変換
printf("WORD(Hi) : 0x%04X\n", endian_data->word[0]);
printf("WORD(Lo) : 0x%04X\n", endian_data->word[1]);
/***************************/
/*バイト表示 */
/***************************/
printf("=======================================\n");
for (byte_cnt = 0; byte_cnt < BYTE_SIZE; byte_cnt++) {
endian_data->byte[byte_cnt] = data->byte[(BYTE_SIZE-1)- byte_cnt];//エンディアン変換
printf("BYTE(%d) : 0x%02X\n", byte_cnt, endian_data->byte[byte_cnt]);
}
/***************************/
/*ビット表示 */
/***************************/
printf("=======================================\n");
#if 0
for (bit_cnt = 0; bit_cnt<BIT_SIZE; bit_cnt++) {
/* ビットの表示 */
printf("BITS(%d) : %u\n", bit_cnt, (data->data>> bit_cnt) & 1);
}
#endif
for (bit_cnt = 0; bit_cnt<BIT_SIZE; bit_cnt++) {
if (((data->data >> bit_cnt) & 1 )== 1) {//2進数変換した値が1の場合
endian_data->bit[(BIT_SIZE-1)- bit_cnt] = '1';//エンディアン変換
}
else if (((data->data >> bit_cnt) & 1) == 0) {//2進数変換した値が0の場合
endian_data->bit[(BIT_SIZE-1)- bit_cnt] = '0';//エンディアン変換
}
printf("BITS(%d) : %c\n", bit_cnt, endian_data->bit[bit_cnt]);
}
}
-
気になる質問をクリップする
クリップした質問は、後からいつでもマイページで確認できます。
またクリップした質問に回答があった際、通知やメールを受け取ることができます。
クリップを取り消します
-
良い質問の評価を上げる
以下のような質問は評価を上げましょう
- 質問内容が明確
- 自分も答えを知りたい
- 質問者以外のユーザにも役立つ
評価が高い質問は、TOPページの「注目」タブのフィードに表示されやすくなります。
質問の評価を上げたことを取り消します
-
評価を下げられる数の上限に達しました
評価を下げることができません
- 1日5回まで評価を下げられます
- 1日に1ユーザに対して2回まで評価を下げられます
質問の評価を下げる
teratailでは下記のような質問を「具体的に困っていることがない質問」、「サイトポリシーに違反する質問」と定義し、推奨していません。
- プログラミングに関係のない質問
- やってほしいことだけを記載した丸投げの質問
- 問題・課題が含まれていない質問
- 意図的に内容が抹消された質問
- 過去に投稿した質問と同じ内容の質問
- 広告と受け取られるような投稿
評価が下がると、TOPページの「アクティブ」「注目」タブのフィードに表示されにくくなります。
質問の評価を下げたことを取り消します
この機能は開放されていません
評価を下げる条件を満たしてません
質問の評価を下げる機能の利用条件
この機能を利用するためには、以下の事項を行う必要があります。
- 質問回答など一定の行動
-
メールアドレスの認証
メールアドレスの認証
-
質問評価に関するヘルプページの閲覧
質問評価に関するヘルプページの閲覧
checkベストアンサー
+1
こんにちは。
単純ミスです。
bit_cnt=0
の時、(BIT_SIZE-1)- bit_cnt
は31
ですのでendian_data->bit[31]
に設定してます。
そして、そのままendian_data->bit[0]
を表示してますが、まだここには値が設定されていませんね。
投稿
-
回答の評価を上げる
以下のような回答は評価を上げましょう
- 正しい回答
- わかりやすい回答
- ためになる回答
評価が高い回答ほどページの上位に表示されます。
-
回答の評価を下げる
下記のような回答は推奨されていません。
- 間違っている回答
- 質問の回答になっていない投稿
- スパムや攻撃的な表現を用いた投稿
評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。
+1
unionのデータの配置はコンパイラ依存となります。パディング(詰め物)が途中に入る可能性があります。
従って32ビットデータ(int)をバイトデータ(char)で取り出したときに同じならびになる保障はありません。
一度DATAをダンプして確認したほうがいいと思います。
投稿
-
回答の評価を上げる
以下のような回答は評価を上げましょう
- 正しい回答
- わかりやすい回答
- ためになる回答
評価が高い回答ほどページの上位に表示されます。
-
回答の評価を下げる
下記のような回答は推奨されていません。
- 間違っている回答
- 質問の回答になっていない投稿
- スパムや攻撃的な表現を用いた投稿
評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。
+1
念のため指摘しておきますが、エンディアンは「バイトデータ」の並び順のことです。エンディアンを反転するのにビット操作はしません。
投稿
-
回答の評価を上げる
以下のような回答は評価を上げましょう
- 正しい回答
- わかりやすい回答
- ためになる回答
評価が高い回答ほどページの上位に表示されます。
-
回答の評価を下げる
下記のような回答は推奨されていません。
- 間違っている回答
- 質問の回答になっていない投稿
- スパムや攻撃的な表現を用いた投稿
評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。
+1
直接の回答からはそれるかもしれませんが・・・
バイト並び順の違いは、ネットワーク通信の際に問題になります。
ですので、標準ライブラリにはこの問題に対処するための関数が用意されています。
man htonl 等で調べれば仕様は分かると思います。
#include <stdio.h>
#include <arpa/inet.h>
int main(int argv, char* arg[]) {
unsigned int data1;
unsigned int data2;
data1 = 305419896;
data2 = htonl( data1 );
printf( "%08X\n", data1 );
printf( "%08X\n", data2 );
return 0;
}
以下はインテル系CPU上で動作する ubuntu 上の動作結果です。
$ gcc -o sample sample.c
$ ./sample
12345678
78563412
投稿
-
回答の評価を上げる
以下のような回答は評価を上げましょう
- 正しい回答
- わかりやすい回答
- ためになる回答
評価が高い回答ほどページの上位に表示されます。
-
回答の評価を下げる
下記のような回答は推奨されていません。
- 間違っている回答
- 質問の回答になっていない投稿
- スパムや攻撃的な表現を用いた投稿
評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。
15分調べてもわからないことは、teratailで質問しよう!
- ただいまの回答率 88.09%
- 質問をまとめることで、思考を整理して素早く解決
- テンプレート機能で、簡単に質問をまとめられる
2016/01/21 22:05
コードを落ち着いて見直すと仰る通り非常に単純なミスでした。
printf関数をbit_cntのループ後に記載して同じようにループ出力することで
解決できました。
本当にありがとうございます。