0

システムのエンディアンを判別するために、マルチバイト整数値を変数に格納し、 ;でラップされたものを介して最初のバイトにアクセスすることを計画しています。例えば:unsigned charunion

union{
    unsigned int val;
    unsigned char first_byte;
} test;

test.val = 1; /* stored in little-endian system as "0x01 0x00 0x00 0x00" */

if(test.first_byte == 1){
    printf("Little-endian system!");
}else{
    printf("Big-endian system!");
}

このテストをプラットフォーム間で移植可能にしたいのですが、C99標準でデータ型のサイズが1バイトunsigned intを超えることが保証されているかどうかはわかりません。さらに、「Cバイト」は技術的には8ビットのサイズである必要はないため、正確な幅の整数型(たとえば、など)を使用することはできません。uint8_tuint16_t

C99標準で少なくとも2バイトのサイズが保証されているCデータ型はありますか?

PSunsigned intが実際に1バイトより大きいと仮定すると、すべてのC99互換プラットフォームで(変数が変数の最初のバイトにアクセスすることで)union期待どおりに動作しますか?first_byteval

4

8 に答える 8

4

int少なくとも 16 ビットの範囲が必要なのでint、ほとんどの実用的なシステムで基準を満たします。short(およびlong、および)も同様long longです。正確に 16 ビットが必要な場合は、int16_tuint16_tが で宣言されているかどうかを確認する必要があります<stdint.h>

CHAR_BITが 8 を超えるシステムについて心配している場合は、もっと頑張らなければなりません。CHAR_BITが 32 の場合、 だけlong longが 2 文字を保持することが保証されます。


C 標準が整数型のサイズについて述べていること

コメントで、Richard J Ross IIIは次のように述べています。

標準では、int のサイズについては、short 以上でなければならないということを除いて、まったく何も述べていません。したがって、たとえば、私が取り組んだ一部のシステムでは 10 ビットになる可能性があります。

反対に、C 標準には、さまざまな型でサポートする必要がある範囲の下限に関する仕様があり、10 ビットのシステムはintC に準拠していません。

具体的には、ISO/IEC 9899:2011 §5.2.4.2.1 Sizes of integer types<limits.h>で、次のように述べています。

¶1 以下の値は、#if 前処理ディレクティブでの使用に適した定数式に置き換えられます。さらに、 と を除いてCHAR_BITMB_LEN_MAX以下は整数昇格に従って変換された対応する型のオブジェクトである式と同じ型を持つ式に置き換えられます。それらの実装定義の値は、同じ符号で示されているものと同じかそれ以上の大きさ (絶対値) でなければなりません。

— ビットフィールド (バイト) ではない最小オブジェクトのビット数 CHAR_BIT 8

[...]

— タイプのオブジェクトの最小値short int

SHRT_MIN -32767// −(2 15 − 1)

— タイプのオブジェクトの最大値short int

SHRT_MAX +32767// 2 15 − 1

— タイプのオブジェクトの最大値unsigned short int

USHRT_MAX 65535// 2 16 − 1

— タイプのオブジェクトの最小値int

INT_MIN -32767// −(2 15 − 1)

— タイプのオブジェクトの最大値int

INT_MAX +32767// 2 15 − 1

— タイプのオブジェクトの最大値unsigned int

UINT_MAX 65535// 2 16 − 1

于 2012-12-27T16:58:10.733 に答える
4

GCC は、システムのエンディアンを与えるいくつかのマクロを提供します: GCC 共通の定義済みマクロ

例(提供されたリンクから):

/* Test for a little-endian machine */
#if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__

もちろん、これは gcc を使用している場合にのみ役立ちます。さらに、エンディアンの条件付きコンパイルは有害と見なされる可能性があります。これに関する素晴らしい記事は次のとおりです。バイトオーダーの誤謬

コンパイラが他のケースをチェックできるように、通常の条件を使用してこれを行うことをお勧めします。すなわち:

if (__BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__)
...
于 2012-12-27T17:08:38.127 に答える
3

いいえ、1バイトよりも大きいことは保証されていませんが、 1バイトよりも小さいint8_t(非ビットフィールド)型はなく、1バイトは256の異なる値を保持できることが保証されています。したがって、とがあればint16_tint8_t1バイトであることが保証されているため、 int16_t2バイトである必要があります。

于 2012-12-27T16:59:02.590 に答える
2

char <= short <= int <= long <= long longC 標準は、 [および同様に]のサイズのみを保証 しunsignedます。したがって、理論的には、すべてのサイズに対して 1 つのサイズしかないシステムが存在する可能性があります。

特定のアーキテクチャでこれがうまくいかないことが本当に重要な場合は、コードに似たようなif (sizeof(char) == sizeof(int)) exit_with_error("Can't do this....");ことをするコードを追加します。

ほぼすべてのマシンで、intまたはshort完全に問題ないはずです。charとが同じサイズのマシンを実際に認識してintいませんが、それらが存在することは 99% 確信しています。これらのマシンには、ネイティブのbyte!= 8 ビット (9 または 14 ビットなど) と、14、18、36、または 28 ビットの単語もある場合があります...

于 2012-12-27T17:03:46.090 に答える
0

少なくともhttp://en.wikipedia.org/wiki/C_data_typesによると、intのサイズは2つの「char」の長さであることが保証されています。したがって、このテストは機能するはずですが、より適切な解決策があるかどうか疑問に思っています。1つは、まれな例外を除いて、ほとんどのアーキテクチャでは、実行時ではなく、コンパイル時にエンディアンが設定されます。ただし、エンディアンを切り替えることができるアーキテクチャはいくつかあります(ARMとPPCは構成可能だと思いますが、ARMは従来LEであり、PPCはほとんどBEです)。

于 2012-12-27T16:58:38.643 に答える
0

適合する実装は、サイズ 1 のすべての基本型を持つことができます (そして、少なくとも 32 ビットのデータを保持します)。ただし、このような実装では、エンディアンの概念は適用されません。

適合する実装が、たとえばリトルエンディアンshortやビッグエンディアンを持つことを禁止するものは何もありませんlong

そのため、整数型ごとに 3 つの結果が考えられます。ビッグ エンディアン、リトルエンディアン、サイズ 1 のいずれかです。理論上の移植性が最大になるように、各型を個別に確認してください。実際には、これはおそらく決して起こりません。

ミドルエンディアン型、または偶数ページのみのビッグエンディアンなどは理論的には可能ですが、そのような実装について考えることさえ控えたいと思います。

于 2012-12-27T17:25:07.873 に答える
0

stdint.hの man ページを見てください( uint_least16_t2 バイト)。

于 2012-12-27T16:55:02.367 に答える
0

答えは基本的に「いいえ」ですが、stdio 関数のインターフェイス要件を満たすには、範囲 [0,UCHAR_MAX] が に収まる必要があり、ホストされた実装では 1 より大きいint暗黙の要件が作成されます (独立した実装では stdio を自由に省略できます)。 sizeof(int)、そして彼らが持つことができない理由はありませんsizeof(int)==1)。したがって、 と仮定するのはかなり安全だと思いますsizeof(int)>1

于 2014-04-26T22:23:36.680 に答える