Cプログラムでは、シリアライズしたい(したがって、charに変換する)long *があります。long は単一の文字に収まらず、サイズはプロセッサによって異なります (4 バイトまたは 8 バイトの場合があります)。
シリアライゼーションとデシリアライゼーションを行う良い方法はありますか?
Cプログラムでは、シリアライズしたい(したがって、charに変換する)long *があります。long は単一の文字に収まらず、サイズはプロセッサによって異なります (4 バイトまたは 8 バイトの場合があります)。
シリアライゼーションとデシリアライゼーションを行う良い方法はありますか?
これは移植可能ですが、printf/scanf を使用するほど非効率的ではありません。
void longtochar(char *buffer, unsigned long number) {
int i;
for (i=0; i<sizeof(long); i++) {
buffer[i] = number & 0xFF; // place bottom 8 bits in char
number = number >> 8; // shift down remaining bits
}
return; // the long is now stored in the first few (2,4,or 8) bytes of buffer
}
そして、もう一度解凍します( long が同じサイズであると仮定します)
long chartolong(char *buffer) {
long number = 0;
int i;
for (i=sizeof(long)-1; i>=0; i--) {
number = number << 8; // left shift bits in long already
number += buffer[i]; // add in bottom 8 bits
}
return number;
}
long は両方のシステムで同じ長さであるという大きな仮定に注意してください。安全に行うには、#include <stdint.h> を使用し、それが提供する型 (uint32_t または uint16_t) を使用します。
また、私のコードには符号なしの長いものがあります。現在、C コンパイラにアクセスできないため、符号付き整数で動作するかどうかを確認できません。メモリが私に役立つ場合、その動作は未定義かもしれません (私がそれをどのように処理するかは問題ではないかもしれませんが)。
char としてシリアル化する必要はありません。long として (ファイルに) fwrite できます。char 配列にシリアル化するには、最初に 1 バイトを投資して int のサイズとバイト順を示します。これは後で必要になります。
すなわち
char *p = &long_array[0];
long 配列に char としてアクセスするには、単純にキャストし、配列の長さに sizeof(long) を掛けて、サイズを char 単位で取得します。
簡単な例でこれを示します。
#include <stdio.h>
main()
{
int aaa[10];
int i;
char *p;
for(i=0;i<sizeof(aaa)/sizeof(aaa[0]);i++)
{
aaa[i] = i;
printf ("setting aaa[%d] = %8x\n",i,aaa[i]);
}
aaa[9] = 0xaabbccdd;
printf ("sizeof aaa (bytes) :%d\n",sizeof(aaa));
printf ("each element of aaa bytes :%d\n",sizeof(aaa[0]));
p = (char*) aaa;
for(i=0;i<sizeof(aaa);i++)
printf ("%d: %8x\n",i,(unsigned char)p[i]);
}
間違った問題を解決している可能性があります。たとえば、int32_t を使用して、固定サイズの int にシリアル化する必要があります。おそらく、プログラム全体でこの固定サイズの型を使用することをお勧めします。そうしないと、64 ビット プログラムが小さいサイズで保存できない (または int64_t を使用できない) 場合に問題が発生します。
32 ビット プラットフォームで 64 ビット セーブをロードする必要がないことがわかっている場合は、気にしないでください。sizeof(long) バイトをファイルに書き出し、sizeof(long) バイトを読み戻すだけです。ただし、間違いを避けるために、データの早い段階でソース プラットフォームを示すフラグを立ててください。
long * longs;
// ...
int numChars = numLongs * sizeof(long);
char* longsAsChars = (char*) longs;
char* chars = malloc(numChars);
memcpy(chars, longsAsChars, numChars);
Cでは、 long のサイズを取得できます
sizeof(long)
ただし、格納された long を複数のプラットフォーム間で転送可能にする必要がある場合は、常に 4 バイトとしてシリアル化する必要があります。いずれにせよ、4 バイト プロセッサではそれ以上の数値を読み取ることができませんでした。
long 配列の先頭を指す char ポインターを作成すると、char の「配列」をインクリメントすると、一度に 8 ビットが得られます。ただし、 long は null で終了しないことに注意してください (必然的にそうなる可能性があります)。そのため、末尾がどこにあるかを追跡する必要があります。
例えば:
long list[MAX];
char *serial = list;
int chunk = sizeof(long);
int k;
for(k=0; k<(MAX*chunk); k++){
// do something with the "char"
}