2016-06-28 62 views
2

我讀/使用C和bswap_從大端小尾數格式寫的二進制文件{16,32,64}從byteswap.h爲字節宏-swapping。Ç40位字節交換(端)

除了40位的位字段以外,所有的值都可以正確讀寫。

bswap_40不存在,我不知道如何做,或者如果更好的解決方案是可能的。

這裏是一個小的代碼示出這樣的問題:

#include <stdio.h> 
#include <inttypes.h> 
#include <byteswap.h> 

#define bswap_40(x) bswap_64(x) 

struct tIndex { 
    uint64_t val_64; 
    uint64_t val_40:40; 
} s1 = { 5294967296, 5294967296 }; 

int main(void) 
{ 
    // write swapped values 
    struct tIndex s2 = { bswap_64(s1.val_64), bswap_40(s1.val_40) }; 
    FILE *fp = fopen("index.bin", "w"); 
    fwrite(&s2, sizeof(s2), 1, fp); 
    fclose(fp); 

    // read swapped values 
    struct tIndex s3; 
    fp = fopen("index.bin", "r"); 
    fread(&s3, sizeof(s3), 1, fp); 
    fclose(fp); 
    s3.val_64 = bswap_64(s3.val_64); 
    s3.val_40 = bswap_40(s3.val_40); 

    printf("val_64: %" PRIu64 " -> %s\n", s3.val_64, (s1.val_64 == s3.val_64 ? "OK" : "Error")); 
    printf("val_40: %" PRIu64 " -> %s\n", s3.val_40, (s1.val_40 == s3.val_40 ? "OK" : "Error")); 

    return 0; 
} 

即代碼被編譯以:

GCC -D_FILE_OFFSET_BITS = 64 -D_LARGEFILE_SOURCE -D_LARGEFILE64_SOURCE swap_40.c -o swap_40

如何定義bswap_40宏用於讀取和寫入這些40位值,交換?

回答

6

通過定義bswap_40是一樣bswap_64,你交換8個字節,而不是5。所以,如果你開始這樣的:

00 00 00 01 02 03 04 05 

你結束了這個:

05 04 03 02 01 00 00 00 

而不是:

00 00 00 05 04 03 02 01 

最簡單的方法來處理這個問題,電子商務bswap_64和右邊的結果由24接班:

#define bswap_40(x) (bswap_64(x) >> 24) 
+0

謝謝你的解決方案,工作就像一個魅力。 –

1

編輯

我有更好的表現寫這個宏(與我最初的代碼進行比較,由此產生更少的組裝說明):

#define bswap40(s)            \ 
    ((((s)&0xFF) << 32) | (((s)&0xFF00) << 16) | (((s)&0xFF0000)) | \ 
    (((s)&0xFF000000) >> 16) | (((s)&0xFF00000000) >> 32)) 

使用:

s3.val_40 = bswap40(s3.val_40); 

...但它可能是一個優化器問題。我認爲他們應該對同樣的事情進行優化。

原貼

我愛dbush的回答更好。我正要寫:

static inline void bswap40(void* s) { 
    uint8_t* bytes = s; 
    bytes[0] ^= bytes[3]; 
    bytes[1] ^= bytes[2]; 
    bytes[3] ^= bytes[0]; 
    bytes[2] ^= bytes[1]; 
    bytes[0] ^= bytes[3]; 
    bytes[1] ^= bytes[2]; 
} 

這是用於切換字節...

+0

謝謝,優化版本很有趣。 –

0
破壞性的內聯函數

我正在用little-endian格式讀取/寫入big-endian格式的二進制文件,使用bytewap.h中的C和bswap_ {16,32,64}宏進行字節交換。

建議採用不同的方法來處理這個問題:更常見的情況是,代碼需要以已知的endian格式讀取文件,然後轉換爲代碼的endian。這可能涉及一個字節交換,它可能不是訣竅是寫代碼在所有條件下工作。

unsigned char file_data[5]; 
// file data is in big endidan 
fread(file_data, sizeof file_data, 1, fp); 

uint64_t y = 0; 
for (i=0; i<sizeof file_data; i++) { 
    y <<= 8; 
    y |= file_data[i]; 
} 

printf("val_64: %" PRIu64 "\n", y); 

uint64_t val_40:40;是不可移植。 int,signed int,unsigned以外的其他類型的位範圍不可移植,並且具有實現指定的行爲。

BTW:打開文件二進制模式:

// FILE *fp = fopen("index.bin", "w"); 
FILE *fp = fopen("index.bin", "wb");