解決済みの質問
質問:No.5791445
暇なときに回答ください
お気に入り投稿に追加する (0人が追加しました)
回答数3
閲覧数1557
最近のCPUのほとんどはリトルエンディアンかビッグエンディアンでしょうか?
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];
とすればいいでしょうか?
投稿日時 - 2010-03-31 00:09:10
質問者が選んだベストアンサー
回答:No.3
PDPエンディアンとかその他の怪しいエンディアンはたぶん絶滅してると考えていいだろうから, 「いまあるプロセッサは全てビッグエンディアンかリトルエンディアン (かどっちでもいい)」と思っていいんだろうけど....
もっと端的にいえば「Windows ならリトルエンディアン」まで言えるだろうけど....
でも, そこまで「速度にこだわらなければならない状況」って, ちょっと想像できないんだけどなぁ.
ちなみにアラインメントの話では, アラインメントを 2のべきに仮定してしまえば「大きいほうから小さい方へのキャスト」は当然に安全です (ただしエンディアンには注意). 逆が危険なのも自明だし, そのときにはそれなりな演算をしなきゃならないことも明らか. ただし
short s=(c[0]<<8)|c[1];
が安全かというとそうでもない. char から int にどう変換されるか, あるいはこの演算結果が short に入らなかったらどうなるのかは問題.
投稿日時 - 2010-03-31 16:46:06
この回答を支持する
(現在0人が支持しています)
お礼
ありがとうございます♪

>PDPエンディアンとかその他の怪しいエンディアンはたぶん絶滅してると考えていいだろうから, 「いまあるプロセッサは全てビッグエンディアンかリトルエンディアン (かどっちでもいい)」と思っていいんだろうけど....
もっと端的にいえば「Windows ならリトルエンディアン」まで言えるだろう


>ちなみにアラインメントの話では, アラインメントを 2のべきに仮定してしまえば「大きいほうから小さい方へのキャスト」は当然に安全です (ただしエンディアンには注意). 逆が危険なのも自明だし, そのときにはそれなりな演算をしなきゃならないことも明らか.


この理解で本当にOKかどうかの確信がなかったので、これですっきりと解決しました!


>でも, そこまで「速度にこだわらなければならない状況」って, ちょっと想像できないんだけどなぁ.

こだわる必要はないかもしれません。ただ、どの道同程度の保証で同じ結果が得られるなら、無駄な処理はないほうがいいとは思います。


>short s=(c[0]<<8)|c[1];
>が安全かというとそうでもない. char から int にどう変換されるか, あるいはこの演算結果が short に入らなかったらどうなるのかは問題.

確かにそうですね。その辺はマクロをつかって、アラインメントに寛容でないCPUの場合ならば、キャストしつつ、とやることにします。

(そういえばWindowsAPIでつかうRGBマクロとか他にも色々そんな感じになってましたねw)
投稿日時 - 2010-03-31 17:01:35
この質問は役に立ちましたか?
5人が「このQ&Aが役に立った」と投票しています
ベストアンサー以外の回答
回答:No.2
どうしてそこまでエディアンに悩む必要があるのでしょうか?

通常のプログラミングであれば処理系に任せればいい話だと思います。
そもそも、CPUの違いを吸収するというのがC言語の
(アセンブラに比し)大きなメリットでもあるわけです。

コンパイラ信用できないならオール・アセンブラで書く方が理にかなってます。

例えば、インターネットで異なるCPUでデータを通信したい等
特殊な場合には
http://wisdom.sakura.ne.jp/system/winapi/winsock/winSock4.html

のような関数が用意されています。

組み込み系等で用意されていなければ
自分で作ればいい話だと思います。

そこでバイトオーダーを吸収させて
後はバイトオーダー気にせずプログラミングする方が
よほど理解しやすいプログラムになると思いますが・・・・

上記にあるshortとcharの変換なら専用関数を作るべきでしょう。
そこでバイトオーダーを注意深くプログラミングする。
#ifdef
等を活用すれば
一つのソースにまとめ上げることもでき
管理も楽だと思いますが・・・・

そして変換が必要なら、関数を呼ぶ。
この原則を徹底させれば、
プログラムのあちこちでバイトオーダーに悩むこともなくなると思います。
投稿日時 - 2010-03-31 09:46:55
この回答を支持する
(現在0人が支持しています)
お礼
ありがとうございます。

>どうしてそこまでエディアンに悩む必要があるのでしょうか?

エンディアンにはそんなには悩んでいません。
異なるCPUでのデータ通信、異なるCPUでバイナリデータのファイル入出力(同じ独自の拡張子のファイルを作るとして)対応を考えるなら、先に考えておかなければ面倒なことになるためなのですが
(逆に言うとそういう場合以外は仰る通りCを使って書く限り必要ないと思います)

アラインメントの概念に対する理解がこれで正しいかどうかの方がたぶん重大です。後はそれが分かれば、おそらくエンディアンの問題に対する解も自然と得られます。
また、この点に関しては、アセンブリ言語で組むとしても、アラインメントに対する理解が完全でないと無理なはずです。

たとえばファイルをchar*バッファに一括読み込みして、それを後で切り分けるケースなどを考えたときに、それを簡単に、よりアラインメントが厳しい型へキャストできると非常に便利な場合があるはずです。
その場合、出力の時点でデータ順番を変えた方がいい可能性があるのではないでしょうか?


また単なるshortとcharの交換などに対して専用関数を作る必要があるかどうかが重要です。
そもそもそういう状況というのは速度を求めている場合だからそうなるということなので、関数化するとオーバーヘッドが生じる可能性があるからです。(inlineキーワードはコンパイラに対する提案で、必ず埋め込まれるとは限らない)

#ifdefと置換マクロなどを使うとしても、結果的にアラインメントに対する理解がないと組めません。
投稿日時 - 2010-03-31 15:45:35
回答:No.1
>Windows, Mac, Linuxに使われているCPUのほとんどはリトルエンディアンかビッグエンディアンでしょうか?
そうですね。 ミドルエンディアン や PDPエンディアン は 少ないと思います。

参考に ウィキペディア ですが.
http://ja.wikipedia.org/wiki/%E3%82%A8%E3%83%B3%E3%83%87%E3%82%A3%E3%82%A2%E3%83%B3
投稿日時 - 2010-03-31 00:42:34
この回答を支持する
(現在0人が支持しています)
お礼
ありがとうございます♪
やはりそうですよね。
大よそ安心できました。


しかし、上のコードも(最近のCPUに絞ったとして)やはり環境依存かなぁ…

ああ、#include <windows.h>使ってるから環境依存とかいう問題はなしとして、考え方という点で、ですw

この場合だと、問題あるとすればアラインメントまわりの問題を克服できてるかどうかにかかってると思うのですが

…やっぱりアラインメントw
気になりますね。
投稿日時 - 2010-03-31 00:55:23
もっと聞いてみる
関連するQ&Aはこちら
(1)リトルエンディアン typedef struct recvData{  int a;  unsigned char b[16]; unsigned char c[8]; unsigned...
仕事上でリトルエンディアン形式、ビッグエンディアン形式を使う?のですが意味がまったく解りません 簡単に言ったら JPEGで容量:1.5M、サイズ:640x640、リトルエンディアン形式 JPEGで容量...
リトルエンディアン、ビッグエンディアンについて 質問があります。 (1)簡単にそのPCがリトルエンディアンなのか、ビッグエンディアン  なのか、分かる方法はありますか?  簡単なCプログラムを書い...
この他の関連するQ&Aをキーワードで探す
プログラミングのサブカテゴリ
[PR] おすすめの注目情報
カテゴリ:C・C++
RSS
-PR-
PR
-PR-