2016-06-28 63 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");