web-dev-qa-db-ja.com

intをchar配列に格納しますか?

4バイトのintをchar配列に格納したい... char配列の最初の4つの場所がintの4バイトになるようにします。

次に、intを配列から引き出したい...

また、誰かがループでこれを行うためのコードを私に与えることができる場合のボーナスポイント... IE 32バイト配列に8 intのように書き込む。

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

みんなありがとう!

編集:intは4バイトであると想定します...

EDIT2:エンディアンについては気にしないでください...私はエンディアンについて心配します。 C/C++で上記を実現するさまざまな方法が欲しいだけです。ありがとう

EDIT3:わからない場合は、低レベルでシリアル化クラスを記述しようとしています...したがって、いくつかの一般的なデータ型をシリアル化するためのさまざまな戦略を探しています。

20
Polaris878

最適な方法ではありませんが、エンディアンセーフです。


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;
22
user184677

バイトオーダーなどを気にしない限り、memcpyがうまくいきます:

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

もちろん、特定の実装でsizeof(int)==4が保証されているわけではありません(実際には、これが実際にfalseである実装もあります)。

ループを書くことはここから簡単です。

39
Pavel Minaev
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;
}

リトルエンディアンマシンでは、a [0]がLSBを保持し、a [3]がMSBを保持することに注意してください。

8
Ashwin
#include <stdio.h>

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

覚えておいてください:

オブジェクトまたは不完全型へのポインタは、別のオブジェクトまたは不完全型へのポインタに変換される場合があります。結果のポインターが指す型に対して正しく配置されていない場合、動作は未定義です。

8
Sinan Ünür

注:最後に割り当てられていない要素を介して共用体にアクセスすることは、未定義の動作です。 (文字が8ビットで整数が4バイトのプラットフォームを想定)0xFFのビットマスクは1文字をマスクするため、

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 [0]は最上位バイトを保持し、arr [3]は最下位バイトを保持します。

編集:ちょうど&&が論理的な「and」であるトリック&&is bit賢明な「and」を理解するだけです。忘れられていたシフトについてのコメントに感謝します。

8
stonemetal

ユニオンを使用しないでください、Pavelは明確にします:

C++は、最後に書き込まれたもの以外のユニオンメンバーへのアクセスを禁止しているため、これはUBです。特に、コンパイラーは、上記のコードを使用してintメンバーへの割り当てを完全に自由に最適化できます。これは、その値が後で使用されないためです(char[4]メンバーの後続の読み取りのみを確認し、そこで意味のある価値を提供する義務はありません)。実際には、特にg ++はそのようなトリックを引くことで知られているため、これは単なる理論ではありません。一方、static_cast<void*>に続けてstatic_cast<char*>を使用しても、動作することが保証されています。

– Pavel Minaev

7
GManNickG

これには、新しい配置を使用することもできます。

void foo (int i) {
  char * c = new (&i) char[sizeof(i)];
}
4
Richard Corden
 
 #include <stdint.h> 
 
 int main(int argc、char * argv []){
/* 8 int inループ*/
 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]); 
/* ^ ^ ^ ^ */
/* |にポイント| | */
/* intとしてキャスト* | | */
/* |のアドレス*/
/* char配列内の場所*/
 
 * intPtr = intArr [i];/* */
} 
 
を指す場所にintを書き込む/ * intを読み取る*/
 for(i = 0; i <8; i ++) {
 intPtr =(int *)&(charArr [i * 4]); 
 intArr [i] = * intPtr; 
} 
 
 char * myArr = malloc(13); 
 int myInt; 
 uint8_t * p8;/*符号なし8ビット整数*/
 uint16_t * p16;/*符号なし16ビット整数*/
 uint32_t * p32;/*符号なし32ビット整数*/
 
/* 4バイト整数以外のサイズを使用して、*/
/* myArrのすべてのビットを1に設定*/
 p8 =(uint8_t *)&(myArr [0]); 
 p16 =(uint16_t *)&(myArr [1]); 
 p32 =(uint32_t *)&(myArr [5]); 
 * p8 = 255; 
 * p16 = 65535; 
 * p32 = 4294967295; 
 
/*値を取得しますバックアウト*/
 p16 =(uint16_t *)&(myArr [1]); 
 uint16_t my16 = * p16; 
 
/* 16ビットを置くintを通常のintに変換*/
 myInt =(int)my16; 
 
} 
 
2
Schlameel
char a[10];
int i=9;

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

これはcharを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になります

1
pari
 union value {[.___。] int i; 
 char bytes [sizeof(int)]; 
}; 
 
 value v; 
 vi = 2; 
 
 char * bytes = v.bytes; 
0
codie