2009-10-05 25 views
17

char配列の最初の4つの位置がintの4バイトであるように、char配列に4バイトのintを格納したいとします。intをchar配列に格納しますか?

その後、私は誰かが私にループ内でこれを行うためのコードを与えることができれば、また...背中配列のうちボーナスポイントを

をint型を引きたい... IEに8つのint型のように書きます32バイトの配列。

int har = 0x01010101; 
char a[4]; 
int har2; 

// write har into char such that: 
// a[0] == 0x01, a[1] == 0x01, a[2] == 0x01, a[3] == 0x01 etc..... 

// then, pull the bytes out of the array such that: 
// har2 == har 

ありがとうございました!

EDIT:intは4バイト...

EDIT2あると仮定しますエンディアンを気にしないでください...私はエンディアンを心配されます。私は上記のC/C++を達成するためのさまざまな方法が必要です。ありがとう

EDIT3:私は低レベルでシリアライゼーションクラスを作成しようとしているので、いくつかの一般的なデータ型をシリアライズするためのさまざまな戦略を探しています。

+8

を行う必要があります...そして、あなたは疑問を持っている場合、その後、あなたはここにコードを投稿することができますし、私たちはあなたをお手伝いします。あなた自身でそれをやろうとしなければ、何も学ばないでしょう。 – jpmelos

+1

LOLこれは宿題ではありません:) – Polaris878

+1

C言語を書いていたら、変数を値で初期化するよりもよく分かります。 – jkeys

答えて

20

最適な方法ではありませんが、エンディアンセーフです。あなたも、このための新しい配置を使用することができます


int har = 0x01010101; 
char a[4]; 
a[0] = har & 0xff; 
a[1] = (har>>8) & 0xff; 
a[2] = (har>>16) & 0xff; 
a[3] = (har>>24) & 0xff; 
+0

harが負の場合、これが問題になりますか? (ビットシフトと負のintについて奇妙なことがあることを覚えていると思う...) –

37

あなたはバイト順と、そのような気にされない限り、memcpyは、トリックを行います:もちろん

memcpy(a, &har, sizeof(har)); 
... 
memcpy(&har2, a, sizeof(har2)); 

を、任意の特定の実装にsizeof(int)==4という保証はありません(これはされている実世界の実装があります実際には偽)。

ここにループを書くのは簡単です。

7

は、労働組合を使用しないでください、パベルは明確:

をC++が書き込まれた最後の1 以外の組合員へのアクセス を禁止しているので、それはU.B.です。特に では、コンパイラは、その値がその後使用 ないので、上記のコード と完全にintに 部材割り当てを離れて最適化 に自由である(それだけchar[4] 部材用 後続のリードを見て、そして持っています に意味のある価値を提供する義務はありません)。 実際には、g ++はそのようなトリックを引き出すために知られている です。だから、 は単なる理論ではありません。一方、 を使用してstatic_cast<void*>を入力した後に static_cast<char*>を入力すると、 の作業が保証されます。

- 心の中でパベルMinaev

+1

C++は、書かれた最後のもの以外の任意の共用体メンバへのアクセスを禁止するため、U.B.です。特に、コンパイラは、その値が後で使用されないため( 'char [4]'メンバの後続の読み込みのみを見ているので)、上記のコードで完全に 'int'メンバへの割り当てを自由に最適化することができます。意味のある価値を提供する義務はありません)。実際には、特にg ++はそのような技を引き出すことで知られているので、これは単なる理論ではありません。一方、 'static_cast 'の後に 'static_cast 'が続くことが保証されています。 –

+0

だから、私はそれを明確にしたことはありません。あなたが気にしないなら、私はアドバイスとしてあなたのコメントを残します。 – GManNickG

+0

私は気にしませんが、それらの 'static_cast'sを修正するのが良いでしょう:) –

7
int main() { 
    typedef union foo { 
     int x; 
     char a[4]; 
    } foo; 

    foo p; 
    p.x = 0x01010101; 
    printf("%x ", p.a[0]); 
    printf("%x ", p.a[1]); 
    printf("%x ", p.a[2]); 
    printf("%x ", p.a[3]); 

    return 0; 
} 

ベア[0] LSBを保持し、[3]リトルエンディアンのマシン上で、MSBを保持していること。

+0

LSBとMSBについてのあなたのコメントは、リトルエンディアンアーキテクチャの場合にのみ当てはまります。 –

+5

このコードの 'p.a'の読み込みは' a'への書き込みが先行しなかったのでU.B.を呼び出します。準拠しているC++の実装では、合法的に 'p.x'への割り当てを完全に最適化することができます。 –

+0

うん、はい、いいえ。正確な結果はU.Bです。プラットフォームのアーキテクチャーに依存しているからです。しかし、異なるタイプの別名を作るための合法的な方法は組合であり、p.aが書かれていることを完全には理解していないコンパイラーには驚くでしょう。実際、組合はgnuの実装における型エイリアシングの最適化に関する*唯一の公式な方法です。 – DigitalRoss

8
#include <stdio.h> 

int main(void) { 
    char a[sizeof(int)]; 
    *((int *) a) = 0x01010101; 
    printf("%d\n", *((int *) a)); 
    return 0; 
} 

に留意してください:

オブジェクトまたは不完全型へのポインタは、異なる オブジェクトまたは不完全型へのポインタに変換することができます。結果のポインターが ポインティング・タイプのために正しく整列されていない場合、その動作は未定義です。

+3

ポインタを変換することはできますが、逆参照することはできません。例えば。あなたは 'int *'を 'float *'(U.B.はありません)に変換することができますが、その 'float * 'を通して何かを書くとすぐにU.Bを打ちます。あなたの例はうまくいきます。なぜなら、 'char * 'を介した書き込みはPODに特に許されており、PODの寿命はメモリが割り当てられるとすぐに始まりますが、これは明らかです。 –

+2

実際、申し訳ありませんが、私は間違っています。この例は依然としてU.Bです。 - 具体的には、 'a'が' int'のために正しく整列されているという保証はありません。 'new'を使って配列を割り当てるとき、配列と同じサイズのオブジェクトに対して正しく整列されるという保証があります。自動変数や静的変数、メンバーフィールドの保証はありません。例えば。ローカル変数の宣言を考えてみましょう: 'char c; char a [4]; ' - 4バイトの境界に' a 'が割り当てられない場合があります。また、いくつかのアーキテクチャでは、 'int *'を使ってその場所に書き込もうとするとクラッシュするでしょう。 '。 –

+0

Pavel、PODとU.Bの意味を明確にできますか?ありがとう – Polaris878

8

注:最後に割り当てられていない要素を介してユニオンにアクセスすることは、未定義の動作です。 よう

char arr[4]; 
int a = 5; 

arr[3] = a & 0xff; 
arr[2] = (a & 0xff00) >>8; 
arr[1] = (a & 0xff0000) >>16; 
arr[0] = (a & 0xff000000)>>24; 

はARRになるだろう0xFFでのビットマスクが一つの文字をマスクします (文字は8ビットとint値は4バイトであるプラットフォームを想定)[0]は最上位バイトとARRを保持する[3]少なくとも保持する。

編集:ちょっと分かりました&はビット賢明です 'と' & &は論理 'と'です。 忘れられたシフトについてのコメントのおかげで。

+0

+1です。これは、特定のバイナリ表現が必要な場合(つまり、LSB/MSBの混乱がない場合)に行く方法です。 –

+4

シフトすることを忘れないでください! – Polaris878

+1

Polaris878で指摘されているように、値に ">>"を使用していないため、最後の3つの割り当ては配列に '0'を設定します。 –

3

void foo (int i) { 
    char * c = new (&i) char[sizeof(i)]; 
} 
0
 
union value { 
    int i; 
    char bytes[sizof(int)]; 
}; 

value v; 
v.i = 2; 

char* bytes = v.bytes; 
+1

あなたの答えにいくつかの説明を追加すると、読者の理解に役立ちます。 –

1
 

    #include <stdint.h> 

    int main(int argc, char* argv[]) { 
     /* 8 ints in a loop */ 
     int i; 
     int* intPtr 
     int intArr[8] = {1, 2, 3, 4, 5, 6, 7, 8}; 
     char* charArr = malloc(32); 

     for (i = 0; i < 8; i++) { 
      intPtr = (int*) &(charArr[i * 4]); 
      /*^  ^^ ^ */ 
      /* point at  | |  |  */ 
      /*  cast as int* |  |  */ 
      /*    Address of |  */ 
      /*   Location in char array */ 

      *intPtr = intArr[i]; /* write int at location pointed to */ 
     } 

     /* Read ints out */ 
     for (i = 0; i < 8; i++) { 
      intPtr = (int*) &(charArr[i * 4]); 
      intArr[i] = *intPtr; 
     } 

     char* myArr = malloc(13); 
     int myInt; 
     uint8_t* p8; /* unsigned 8-bit integer */ 
     uint16_t* p16; /* unsigned 16-bit integer */ 
     uint32_t* p32; /* unsigned 32-bit integer */ 

     /* Using sizes other than 4-byte ints, */ 
     /* set all bits in myArr to 1   */ 
     p8 = (uint8_t*) &(myArr[0]); 
     p16 = (uint16_t*) &(myArr[1]); 
     p32 = (uint32_t*) &(myArr[5]); 
     *p8 = 255; 
     *p16 = 65535; 
     *p32 = 4294967295; 

     /* Get the values back out */ 
     p16 = (uint16_t*) &(myArr[1]); 
     uint16_t my16 = *p16; 

     /* Put the 16 bit int into a regular int */ 
     myInt = (int) my16; 

    } 

1
char a[10]; 
int i=9; 

a=boost::lexical_cast<char>(i) 

これがintおよびその逆に文字を変換するための最良の方法ですました。

boost :: lexical_castの代わりにsprintfがあります。

char temp[5]; 
temp[0]="h" 
temp[1]="e" 
temp[2]="l" 
temp[3]="l" 
temp[5]='\0' 
sprintf(temp+4,%d",9) 
cout<<temp; 

出力は次のようになります。たぶん、あなたはあなた自身の宿題をhell9

関連する問題