2000年あたり以降に出た
Windows, Mac, Linuxに使われているCPUのほとんどはリトルエンディアンかビッグエンディアンでしょうか?
また、たとえば以下のような方法でエンディアンを調べられると考えていいのでしょうか?(VC++です)
#include <windows.h>
void GetEndian4(char* c){
unsigned __int32 a=0x03020100;
BYTE *b = (BYTE*)&a, i=4;
while (i--) c[i]=b[i];
}
//////////
const char e[4]={};
GetEndian4( const_cast<char*>(e) );
//eが 0,1,2,3 になればリトルエンディアン
//3,2,1,0 になればビッグエンディアン
//PDP-エンディアンだと 2,3,0,1 …のはず
(または2択ならこれだけでも判断可能…?)
short s=1;
printf( *(char*)&s ? "リトルエディアン\n" : "ビッグエディアン\n" );
あとここでもアラインメントの問題が絡みますが、このように
アラインメントが(2のべき乗だとして)大きいであろう方から小さいであろう方にキャストする分には安全で、逆に
sizeof(short) == sizeof(char)*2 として
char c[2]={1,0};
short s=*(short*)&c;
というのは危険な場合がある、ということでしょうか?
また、その場合は
たとえばビッグエンディアンなら
short s=(c[0]<<8)|c[1];
とすればいいでしょうか?
No.3ベストアンサー
- 回答日時:
PDPエンディアンとかその他の怪しいエンディアンはたぶん絶滅してると考えていいだろうから, 「いまあるプロセッサは全てビッグエンディアンかリトルエンディアン (かどっちでもいい)」と思っていいんだろうけど....
もっと端的にいえば「Windows ならリトルエンディアン」まで言えるだろうけど....
でも, そこまで「速度にこだわらなければならない状況」って, ちょっと想像できないんだけどなぁ.
ちなみにアラインメントの話では, アラインメントを 2のべきに仮定してしまえば「大きいほうから小さい方へのキャスト」は当然に安全です (ただしエンディアンには注意). 逆が危険なのも自明だし, そのときにはそれなりな演算をしなきゃならないことも明らか. ただし
short s=(c[0]<<8)|c[1];
が安全かというとそうでもない. char から int にどう変換されるか, あるいはこの演算結果が short に入らなかったらどうなるのかは問題.
ありがとうございます♪
>PDPエンディアンとかその他の怪しいエンディアンはたぶん絶滅してると考えていいだろうから, 「いまあるプロセッサは全てビッグエンディアンかリトルエンディアン (かどっちでもいい)」と思っていいんだろうけど....
もっと端的にいえば「Windows ならリトルエンディアン」まで言えるだろう
>ちなみにアラインメントの話では, アラインメントを 2のべきに仮定してしまえば「大きいほうから小さい方へのキャスト」は当然に安全です (ただしエンディアンには注意). 逆が危険なのも自明だし, そのときにはそれなりな演算をしなきゃならないことも明らか.
この理解で本当にOKかどうかの確信がなかったので、これですっきりと解決しました!
>でも, そこまで「速度にこだわらなければならない状況」って, ちょっと想像できないんだけどなぁ.
こだわる必要はないかもしれません。ただ、どの道同程度の保証で同じ結果が得られるなら、無駄な処理はないほうがいいとは思います。
>short s=(c[0]<<8)|c[1];
>が安全かというとそうでもない. char から int にどう変換されるか, あるいはこの演算結果が short に入らなかったらどうなるのかは問題.
確かにそうですね。その辺はマクロをつかって、アラインメントに寛容でないCPUの場合ならば、キャストしつつ、とやることにします。
(そういえばWindowsAPIでつかうRGBマクロとか他にも色々そんな感じになってましたねw)
No.2
- 回答日時:
どうしてそこまでエディアンに悩む必要があるのでしょうか?
通常のプログラミングであれば処理系に任せればいい話だと思います。
そもそも、CPUの違いを吸収するというのがC言語の
(アセンブラに比し)大きなメリットでもあるわけです。
コンパイラ信用できないならオール・アセンブラで書く方が理にかなってます。
例えば、インターネットで異なるCPUでデータを通信したい等
特殊な場合には
http://wisdom.sakura.ne.jp/system/winapi/winsock …
のような関数が用意されています。
組み込み系等で用意されていなければ
自分で作ればいい話だと思います。
そこでバイトオーダーを吸収させて
後はバイトオーダー気にせずプログラミングする方が
よほど理解しやすいプログラムになると思いますが・・・・
上記にあるshortとcharの変換なら専用関数を作るべきでしょう。
そこでバイトオーダーを注意深くプログラミングする。
#ifdef
等を活用すれば
一つのソースにまとめ上げることもでき
管理も楽だと思いますが・・・・
そして変換が必要なら、関数を呼ぶ。
この原則を徹底させれば、
プログラムのあちこちでバイトオーダーに悩むこともなくなると思います。
ありがとうございます。
>どうしてそこまでエディアンに悩む必要があるのでしょうか?
エンディアンにはそんなには悩んでいません。
異なるCPUでのデータ通信、異なるCPUでバイナリデータのファイル入出力(同じ独自の拡張子のファイルを作るとして)対応を考えるなら、先に考えておかなければ面倒なことになるためなのですが
(逆に言うとそういう場合以外は仰る通りCを使って書く限り必要ないと思います)
アラインメントの概念に対する理解がこれで正しいかどうかの方がたぶん重大です。後はそれが分かれば、おそらくエンディアンの問題に対する解も自然と得られます。
また、この点に関しては、アセンブリ言語で組むとしても、アラインメントに対する理解が完全でないと無理なはずです。
たとえばファイルをchar*バッファに一括読み込みして、それを後で切り分けるケースなどを考えたときに、それを簡単に、よりアラインメントが厳しい型へキャストできると非常に便利な場合があるはずです。
その場合、出力の時点でデータ順番を変えた方がいい可能性があるのではないでしょうか?
また単なるshortとcharの交換などに対して専用関数を作る必要があるかどうかが重要です。
そもそもそういう状況というのは速度を求めている場合だからそうなるということなので、関数化するとオーバーヘッドが生じる可能性があるからです。(inlineキーワードはコンパイラに対する提案で、必ず埋め込まれるとは限らない)
#ifdefと置換マクロなどを使うとしても、結果的にアラインメントに対する理解がないと組めません。
No.1
- 回答日時:
>Windows, Mac, Linuxに使われているCPUのほとんどはリトルエンディアンかビッグエンディアンでしょうか?
そうですね。 ミドルエンディアン や PDPエンディアン は 少ないと思います。
参考に ウィキペディア ですが.
http://ja.wikipedia.org/wiki/%E3%82%A8%E3%83%B3% …
ありがとうございます♪
やはりそうですよね。
大よそ安心できました。
しかし、上のコードも(最近のCPUに絞ったとして)やはり環境依存かなぁ…
ああ、#include <windows.h>使ってるから環境依存とかいう問題はなしとして、考え方という点で、ですw
この場合だと、問題あるとすればアラインメントまわりの問題を克服できてるかどうかにかかってると思うのですが
…やっぱりアラインメントw
気になりますね。
お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!
関連するカテゴリからQ&Aを探す
おすすめ情報
- ・漫画をレンタルでお得に読める!
- ・人生のプチ美学を教えてください!!
- ・10秒目をつむったら…
- ・あなたの習慣について教えてください!!
- ・牛、豚、鶏、どれか一つ食べられなくなるとしたら?
- ・【大喜利】【投稿~9/18】 おとぎ話『桃太郎』の知られざるエピソード
- ・街中で見かけて「グッときた人」の思い出
- ・「一気に最後まで読んだ」本、教えて下さい!
- ・幼稚園時代「何組」でしたか?
- ・激凹みから立ち直る方法
- ・1つだけ過去を変えられるとしたら?
- ・【あるあるbot連動企画】あるあるbotに投稿したけど採用されなかったあるある募集
- ・【あるあるbot連動企画】フォロワー20万人のアカウントであなたのあるあるを披露してみませんか?
- ・映画のエンドロール観る派?観ない派?
- ・海外旅行から帰ってきたら、まず何を食べる?
- ・誕生日にもらった意外なもの
- ・天使と悪魔選手権
- ・ちょっと先の未来クイズ第2問
- ・【大喜利】【投稿~9/7】 ロボットの住む世界で流行ってる罰ゲームとは?
- ・推しミネラルウォーターはありますか?
- ・都道府県穴埋めゲーム
- ・この人頭いいなと思ったエピソード
- ・準・究極の選択
デイリーランキングこのカテゴリの人気デイリーQ&Aランキング
-
fgetsなどのときのstdinのバッ...
-
文字列から空白を取り除きたい...
-
間接操作のレベルとは
-
Linuxでフォルダ内全ファイル名...
-
テキストデータをそのままバイ...
-
構造体のアライメント調整
-
Win32APIでのエディットボック...
-
switch文で文字を比較すること...
-
pingの結果を取得する方法
-
バイトスワップをやりたい
-
charからLPTSTRへの変換方法
-
TCHAR文字列?の特定部分の数字...
-
【C言語】構造体内の領域解放(...
-
CStringをwchar_tに変換したい
-
strsetという関数
-
干支のプログラム
-
_TCHAR*での引数の読み込み
-
ネットワークにつながっている...
-
間接参照のレベルが異なっています
-
'const char *' 型は 'char *' ...
マンスリーランキングこのカテゴリの人気マンスリーQ&Aランキング
-
fgetsなどのときのstdinのバッ...
-
CStringをwchar_tに変換したい
-
charでの計算?
-
文字列から空白を取り除きたい...
-
charからLPTSTRへの変換方法
-
'const char *' 型は 'char *' ...
-
テキストデータをそのままバイ...
-
配列をnビットシフトする
-
半角カナ→16進
-
double型の値をchar配列に変換...
-
sprintfに同じ変数は使えるか
-
ファイル名である文字列からbas...
-
ネットワークにつながっている...
-
ftoa の作り方
-
間接操作のレベルとは
-
型変換
-
C言語です
-
C言語のfor文です。 繰り返しの...
-
Win32APIでのエディットボック...
-
【C言語】文字型と整数型の違い
おすすめ情報