![](http://oshiete.xgoo.jp/images/v2/pc/qa/question_title.png?5a7ff87)
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で質問しましょう!
似たような質問が見つかりました
- C言語・C++・C# const char** p;のとき、free(p)でC4090エラーとなるのはなぜですか 3 2023/03/31 16:28
- C言語・C++・C# 宣言する関数の形が決まっている状態で、 str1とstr2の文字列をこの順に引っ付けてstrに保存し 2 2022/05/30 18:21
- C言語・C++・C# c言語でユーザ関数を利用して入力された文字列を反転させるプログラムを作りたいです。 3 2023/01/29 19:47
- C言語・C++・C# c言語配列の結合についてです。 なぜうまくいかないのでしょうか。 #include <stdio.h 4 2022/05/30 22:42
- C言語・C++・C# C言語初心者 構造体 課題について 1 2023/03/10 19:30
- C言語・C++・C# c言語の問題の説明、各所ごとに 5 2023/07/26 11:03
- C言語・C++・C# Cのdoubleの浮動小数点表示について 3 2023/04/17 13:14
- C言語・C++・C# プログラムが書けません。 4 2023/01/22 22:57
- C言語・C++・C# C言語で再起関数とポインタを用いて文字列反転をする方法がわかりません。 4 2023/04/29 20:32
- C言語・C++・C# C言語のエラーについて 2 2022/07/11 13:56
関連するカテゴリからQ&Aを探す
デイリーランキングこのカテゴリの人気デイリーQ&Aランキング
-
fgetsなどのときのstdinのバッ...
-
charでの計算?
-
'const char *' 型は 'char *' ...
-
文字列から空白を取り除きたい...
-
エンディアン:2バイトのデー...
-
C言語のfor文です。 繰り返しの...
-
テキストデータをそのままバイ...
-
charからLPTSTRへの変換方法
-
atoi( ) の反対をやりたい
-
C言語です
-
C言語プログラミングについて(...
-
C言語、リダイレクト
-
Win32APIでのエディットボック...
-
int型からchar型への変換
-
CStringをwchar_tに変換したい
-
【C言語】文字型と整数型の違い
-
strncpyと_tcsncpy_sのヌルの扱...
-
double型の値をchar配列に変換...
-
ソースコードエラー
-
【C言語】テキストファイル内の...
マンスリーランキングこのカテゴリの人気マンスリーQ&Aランキング
-
fgetsなどのときのstdinのバッ...
-
C言語のfor文です。 繰り返しの...
-
文字列から空白を取り除きたい...
-
charからLPTSTRへの変換方法
-
charでの計算?
-
配列をnビットシフトする
-
CStringをwchar_tに変換したい
-
c++ 文字列を入力して、一文字...
-
str系関数を使わずに二つの文字...
-
間接操作のレベルとは
-
int main()の・・・
-
C言語の入力した文字を反転させ...
-
atoi( ) の反対をやりたい
-
switch文で文字を比較すること...
-
テキストデータをそのままバイ...
-
Win32APIでのエディットボック...
-
double型の値をchar配列に変換...
-
干支のプログラム
-
コンパイルエラー invalid ope...
-
間接参照のレベルが異なっています
おすすめ情報