No.4ベストアンサー
- 回答日時:
> コンパイラは gcc とお考えください。
手元には古い gcc しかありませんが,それでちょっと調べてみました.
/usr/include/bits/endian.h で
#define __BYTE_ORDER __LITTLE_ENDIAN
というのがありました.これを使えばいいのでは? (確信なし)
なお,#include するのは <bits/endian.h> ではなく <endian.h> です.
No.11
- 回答日時:
#9です
アラインメントの話も出てきてたのでそちらにも返答をしておきます。
アラインメントを処理系が勝手に決めて、しかも変更できないとしたら、「一気にバイナリデータを、構造体配列に読み込む」ことができなくなってしまう可能性がありますね。
バイナリデータに合わせてアラインメントを調整するとどうなるでしょう。
ゲームだとアラインメントを無くしてデータサイズを切り詰めたりすることもあるでしょうか。
インテル系のCPUならアラインメントがどんなでもあらゆるデータ型にそのままアクセスできます(若干の処理速度の低下はあります)が、例えばARMなら奇数バイトからのshort(16ビット)型のアクセスはハードウェアレベルで不可能です。
要するに「一気にバイナリデータを、構造体配列に読み込む」ことに拘るのがいちばん無駄なことです。
No.10
- 回答日時:
#9です
マクロを使ってもビッグエンディアンのマシンで実行時にバイト位置を入れ替える処理が不要にはならないのでは?
リトルエンディアンに限定しても「一気にバイナリデータを、構造体配列に読み込む」のが期待通り動作することが【特定の条件下以外では】保証されませんし、言語規格で保証された範囲で読み書きするルーチンを作っておくほうが後々まで役に立つと思います。
どうしてもプログラム側で「一気にバイナリデータを、構造体配列に読み込む」以上に無駄なことしたくなければ、「一部がビッグエンディアン」のマシンを捨てて「一気にバイナリデータを、構造体配列に読み込む」ことのできるマシンに入れ替えてもらいましょう。
ご回答ありがとうございます。
マクロを使ってもビッグエンディアンのマシンで実行時にバイト位置を入れ替える処理が不要にはならないのでは?
これはバイナリーデータを機種にあわせて、最初から正しいエンディアンにしておけばいいです。画面の解像度など機種よりちがいますから、画像データなどバイナリデータはも機種ごとに違うものになるので、構造体のデータも機種ごとに違うものになるのは私の場合は気になりません。しかし、ソースはPS2、WII、DS、開発機のcygwinで同じ物を使いたいので、できればENDHIANはマクロで処理したいのです。
報告が送れて申し訳なかったのですが、WII用のコンパイラで __BIG_ENDIAN__ が定義済みマクロとして使えることを確認できました。またこれ以外のマシンはすべてリトルエンディアンですので、これで問題は解決いたしました。
前にお答えいただいた方々にもお礼を申し上げます。ありがとうございました。
No.9
- 回答日時:
そもそも1バイトずつ読み書きすれば、実行側がビッグエンディアンかリトルエンディアンか意識する必要はないのでは?
fread(&l, sizeof(long), 1, fp);
とか
b[0] = fgetc(fp);
b[1] = fgetc(fp);
b[2] = fgetc(fp);
b[3] = fgetc(fp);
l = *(long*)&b[0];
みたいなことをやらなければ良いだけ。
バイナリがリトルエンディアンと分かっているなら
l = (b[3] << 24) | (b[2] << 16) | (b[1] << 8) | b[0];
で良くね?
ご回答ありがとうございます。
これも、一気にバイナリデータを、構造体配列に読み込むのと比べて、無駄なコードが存在することになります。エンディアンやアラインメントはコンパイルの時点ではコンパイラは知っているはずなので、実行時になにかするのは無駄な処理のように思います。
No.8
- 回答日時:
質問ではマクロでとなっているので、回答として的確だと言えないかも知れませんが、
共通であるバイナリデータをネットワークバイトオーダー(ビッグエンディアン)に
統一してしまえば良いのでは?可搬性はぐんと高くなります。
そのために、バイナリデータを出力するときは
htons、htonl
でネットワークバイトオーダーに変換し、バイナリデータを読み込むときは
ntohs、ntohl
を使用してホストのバイトオーダーに変換する。
ソースは共通にできるはずです。
ご回答ありがとうございます。
ご回答のやりかただと、バイトオーダーを変更するコードが無駄なコードになってしまいます。まあ、たいしたことはないのですが、単なるこだわりです。
No.7
- 回答日時:
GCCであれば、__LITTLE_ENDIAN__のようなマクロがあらかじめ定義されたと思います。
ただ、すべてのターゲットで一貫性のある定義が行われるかどうかは調査しないとわかりません。ただ、使用する処理系が限られていますので、上記のようなマクロが使えない場合でも、CPUを示すマクロなどを使って個別対応できるかと思います。(エンディアン判別用のヘッダを作るのがよいでしょうね)MIPSなどのバイエンディアンのCPUでは、バイトオーダーをコンパイルオプションで指定することになるので、むしろ確実に"あらかじめ定義されたマクロ"で判別できるはずです。
No.6
- 回答日時:
> コンパイラはコンパイル時には次のような静的なデータをコンパイルする時には
> エンディアンをわかっていなければならないはずと思うのですが。
> (以下略)
バイエンディアン CPU の話ですか?
私も使ったことはないので推測ですが,デフォルトでは初期状態 (リセット直後) の
エンディアンを使うのではないでしょうか.また,エンディアンを指定する #pragma
もあるのかもしれません.
推測の上に余談ですが,データのエンディアンと,即値のエンディアンが異なる可能性
もありそうですね.(ああ,ややこしい….)
No.5
- 回答日時:
一応、endian.h ていう、半標準のヘッダがあって、たとえば、
http://www.math.kobe-u.ac.jp/~kodama/tips-C-endi …
の「マクロによる判定」のようにすれば、いいことになってます。
あるいは、(中身は同じですが)boost/detail/endian.hppをincludeすれば、
BOOST_LITTLE_ENDIAN,BOOST_BIG_ENDIAN,BOOST_PDP_ENDIAN
のどれかが定義されます。
No.3
- 回答日時:
> #ifdef BIG_ENDIAN
エンディアンを定義している標準的なマクロというものはおそらくないのではないかと思います.
(知っていれば私もとっくに使っていたはず.)
だから,上記のようなマクロは,プログラマが処理系ごとに定義せざるを得ないでしょう.
エンディアン判定関数で動的に判定すれば,それが不要になります.
(といっても,それで節約できる手間はわずかですけど.)
それに,(私は使ったことありませんが) エンディアンを動的に切り替えられる
バイエンディアンの CPU というのもあります.そういう CPU に対しては,
そもそも上記のようなマクロを定義することはできません.
というわけで,エンディアン判定関数は無駄ではないと思います.
エンディアン (Wikipedia)
http://ja.wikipedia.org/wiki/%E3%82%A8%E3%83%B3% …
ご回答ありがとうございます。
マクロは無いのですね。
となりますと、Makefile に
CFLAGS += -D BIG_ENDIAN
とでも記述してやるしかないのでしょうか?
この記述自体はたいした手間でもありませんが、後から仲間に、
「そんなの、XXXXXX を使えばいいじゃん、なんでわざわざこんな定義をする必要があるの?」などと言われるとくやしいので質問しました。
コンパイラはコンパイル時には次のような静的なデータをコンパイルする時にはエンディアンをわかっていなければならないはずと思うのですが。
int xxx=0x12345678;
xxxが 12 34 56 78 なのか 78 56 34 12 なのかはコンパイル時に決定していないとコンパイラは困るのではありませんか?
No.2
- 回答日時:
ファイル内のどのデータがビッグエンディアンになるのかは
事前に (仕様として) わかっていて,CPU 側のエンディアンを
知りたいということでしょうか?
C/C++ 関数・マクロ集 (処理系・OS 非依存)
http://www5d.biglobe.ne.jp/~noocyte/Programming/ …
・エンディアンに関する関数・マクロ
・実行時にエンディアンを判定する関数
・エンディアンを変換 (big ⇔ little) する関数およびマクロ (CHAR_BIT 対応)
・エンディアン名を取得する関数 (あらゆる4バイト・エンディアンおよび CHAR_BIT に対応)
・メモリ上のデータ操作関数・マクロ
・データ (バイト列) をバイト逆順にする.
この回答への補足
コンパイラを特定しないといけませんでした。コンパイラは gcc とお考えください。CPU は Intel系(開発に使うPC)、ARM(DS)、MIPS(PS2、PSP)、PowerPC(WII) です。
補足日時:2007/05/21 01:06ご回答ありがとうございます。
エンディアンを判定する関数というのは無駄ではないかと思います。
コンパイル時にはCPUが決まっているので、コンパイラはエンディアンを知っているはずであり、実行時に判定するコードは無駄なコードでないかと思います。
#ifdef BIG_ENDIAN
// エンディアンの変換処理
#endif
という感じで使えるマクロがありはず、と思うのですが。
お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!
似たような質問が見つかりました
- Excel(エクセル) エクセルのマクロについて教えてください。 7 2023/01/13 13:33
- Visual Basic(VBA) vbaエクセルマクロについて あるデータを作成し、デスクトップに.xlsx形式で保存するマクロを作成 2 2023/03/02 18:54
- Visual Basic(VBA) vbaエクセルマクロについて あるデータを作成し、デスクトップに.xlsx形式で保存するマクロを作成 6 2023/03/03 18:05
- 消費者問題・詐欺 通っている日焼けサロンなのですが、ランプが切れていても交換をしない、マシンが故障しても平気で数週間修 2 2022/10/10 10:55
- Visual Basic(VBA) vbaエクセルマクロ RemoveDuplicatesについて 重複したものがあれば行を削除するとい 1 2023/02/27 18:49
- Excel(エクセル) セルを数式で指定する方法 5 2022/04/13 16:55
- Visual Basic(VBA) エクセルのマクロについて教えてください。 7 2023/07/04 09:18
- Visual Basic(VBA) 特定の文字を簡単な操作で半角スペースに変換するか削除したい 2 2022/11/01 10:35
- 計算機科学 これは迷路を解くというよりも、いかに速く最速で走り切れる経路を見出せるかや、マシン性能、プログラミン 3 2023/07/17 16:27
- Visual Basic(VBA) エクセルのマクロについて教えてください。 1 2023/07/13 12:31
関連するカテゴリからQ&Aを探す
おすすめ情報
デイリーランキングこのカテゴリの人気デイリーQ&Aランキング
-
Excel・Word リサーチ機能を無...
-
エクセルで特定の列が0表示の場...
-
Excel マクロ VBA プロシー...
-
他人が作ったマクロの理解
-
特定のPCだけ動作しないVBAマク...
-
メッセージボックスのOKボタ...
-
エクセルで別のセルにあるふり...
-
一つのTeratermのマクロで複数...
-
ExcelのVBA。public変数の値が...
-
エクセルに張り付けた写真のフ...
-
エクセルのマクロをセルの値に...
-
Wordのマクロでクリップボード...
-
VBScript VisioをPDFに変換
-
PDF出力マクロについて。マクロ...
-
Excel VBAからAccessマクロを実...
-
ExcelVBAでPDFを閉じるソース
-
EXCELのVBAでRange("A1:C4")を...
-
エクセル VBA実行中のApplicati...
-
VBA アドインについて お詳しい...
-
TERA TERMを隠す方法
マンスリーランキングこのカテゴリの人気マンスリーQ&Aランキング
-
Excel・Word リサーチ機能を無...
-
特定のPCだけ動作しないVBAマク...
-
エクセルで特定の列が0表示の場...
-
Excel マクロ VBA プロシー...
-
メッセージボックスのOKボタ...
-
一つのTeratermのマクロで複数...
-
エクセルに張り付けた写真のフ...
-
ExcelのVBA。public変数の値が...
-
TERA TERMを隠す方法
-
Excelのマクロ(VBA)は、同じ...
-
ExcelVBAでPDFを閉じるソース
-
Excel VBAからAccessマクロを実...
-
EXCELのVBAでRange("A1:C4")を...
-
#defineの定数を文字列として読...
-
マクロ実行時、ユーザーフォー...
-
エクセルのマクロをセルの値に...
-
Outlookにて既にウィドウ単体で...
-
エクセルで別のセルにあるふり...
-
マクロで空白セルを詰めて別シ...
-
TeraTermマクロの文字列結合
おすすめ情報