2011-07-16 8 views
2

この関数がエンディアンを決定するかどうか不思議です。AシステムがC言語を使用してBig EndianまたはLittle Endianを使用するかどうかを調べる

テストsomeIntがリトルエンディアンで格納されている場合、テストは1に等しいビットマスクです。

ビットマスクでは、0x1000はマシンのエンディアンスタイルに一致するように変換されるか、または「定数」になりますか?

#include <stdio.h> 

int isBigEndian(){ 
    int someInt =0x0001; 
    if(someInt & 0x0100 == 1) 
     return 1; 
    else 
     return 0; 
} 

int main(){ 
    int returnVal = isBigEndian(); 
    printf("return val is %d", returnVal); 
} 
+0

システムコールやその他のAPIが必要です。あなたはどのプラットフォームをターゲットにしていますか? –

+2

ランタイム機能は必要ありません。これはコンパイル時に知られているものです。 –

答えて

6

定数はシステムのネイティブエンディアンにも格納されているため、この関数は常にゼロを返します。はるかに良い賭けはあなたの質問に答えるシステムAPIを使うことです。移植可能でなければならない場合は、おそらくval == ntohl(val)と比較してエンディアンを決めることができます。

+0

私の質問に答えてくれてありがとう。 – Jesse

+1

'ntohl'(ソケットヘッダのインクルード)に依存しない答えはより良いようです。 – bobobobo

1

int値をsizeof(int)要素のcharに変換する方がよいでしょう。どのように見えるか見てください。

また、コードは非常に具体的なsizeof(int)に依存しています。あなたはそうしてはいけません。

になり
#include <stdio.h> 
#include <stdlib.h> 
#include <string.h> 

int main() 
{ 
    int a = 0xabcdef42; 
    unsigned int i; 
    char *s = calloc(sizeof(a) + 1, sizeof(s[0])); 
    memcpy(s, &a, sizeof(a)); 
    printf("%x\n", a); 
    for (i = 0; i < sizeof(a); i++) 
     printf("%x ", (unsigned char)s[i]); 
    printf("\n"); 
    free(s); 
    return 0; 
} 

(私のマシンは、IntelのCPUを持っている)

abcdef42 
42 ef cd ab 

文字を印刷しますが、符号なしに変換することを確認し、そうでなければ、符号拡張によって引き起こさ面白いffffffef値が表示されます。

4

私は何を使用したいことはこれです:

union { 
    short s; 
    char b[2]; 
} endian; 

endian.s = 1; 
little_endian = endian.b[0] == 1; 
+0

' == 1'を削除して、単に 'endian.b [0]'という値を使うことができます。 –

2

厳密に言えば、完全にANSI Cに準拠している唯一の方法は、可能なすべてのint型の値を反復処理し、それらはすべてあなたが望む表現と一致することを確認することであろう。しかし、あなたが使用するすべてのシステムが、リトルエンディアン、ビッグエンディアン、またはミックスエンディアン(つまり、グレイコードまたはBCDのような変わったものではない)と仮定できる場合は、次のようにしてください:

static const unsigned int testvec = 0x01020304; 
static const unsigned char letest[4] = { 0x04, 0x03, 0x02, 0x01 }; 
static const unsigned char betest[4] = { 0x01, 0x02, 0x03, 0x04 }; 

int isle() { 
    return !memcmp(&testvec, letest, 4); 
} 

int isbe() { 
    return !memcmp(&testvec, betest, 4); 
} 

バイト表現を見ない場合(つまり、生のバイトを見るためにポインタをキャストしない場合)、使用されているバイトオーダーを知ることはできません。 0x00010x1000両方が等しくバイトスワップ(及び0x0001のリトルエンディアン表現が01 00、ない10 00あるため)であるため0x0001 & 0x1000は、すべてのCの実装に0です。

+0

あなたはたぶんその最後の '0x03'が' 0x04'であることを意味しました... –

+0

@Chris、確かに私はします!私は実際にビッグエンディアンシステムを実際に使用する頻度は低いですね。 :) – bdonlan

1

This questionには本当に素晴らしい回答があります(C++とC99の文脈ではありますが)。コメントをチェックしてください、彼らは非常に洞察力があります。

Linux/Unixまたはglibc(mingw/cygwin)を使用するものでは、 endian.hヘッダーファイルが用意されています。 クロスプラットホームであるboost implementationをチェックして、必要に応じて自分で実装するためのヒントを得ることもできます。

関連する問題