2017-05-04 73 views
0

我一直在写R2K对象模块,并且在符号表条目写入文件时遇到了麻烦。我一直试图使用memcpy将存储在sym_table中的符号表条目放入一个名为bytes_sym的字节整数的数组中,然后将其写入文件。它复制正确的大小,但由于某种原因而乱放字节的位置。这里是我的代码:memcpy混合结构的内容?

/* 
** symbol table entry 
*/  
typedef 
struct syment { 
    uint32_t flags;  /* flag word */ 
    uint32_t value;  /* value associated with this symbol */ 
    uint32_t sym;  /* symbol name's index into string table */ 
} 
    syment_t; 

// header->data[8] is the number of symbol table entries 
int sym_length = header->data[8] * sizeof(syment_t); 

uint8_t bytes_sym[sym_length]; 

for(int i = 0; i < header->data[8]; i++){ 
    memcpy(&bytes_sym[i * sizeof(syment_t)], &sym_table[i], sizeof(syment_t)); 
} 
fwrite(bytes_sym, sym_length, 1, file); 

// prints the newly copied symbol table section one byte at a time 
// I know it's gross to look at, but it's only for testing :p 
printf("New Symtab:\n"); 
for(int i = 0; i < sym_length; i++){ 
    printf("0x%x ", bytes_sym[i]); 
} 
printf("\n"); 

写作之前,该字节的值是:

0x0 0x0 0x0 0xb1 0x0 0x40 0x0 0x2c 0x0 0x0 0x0 0x0 
0x0 0x0 0x0 0xa3 0x10 0x0 0x0 0x20 0x0 0x0 0x0 0x5 
0x0 0x0 0x40 0xb1 0x0 0x40 0x0 0x38 0x0 0x0 0x0 0xb 
0x0 0x0 0x0 0xa1 0x0 0x40 0x0 0x14 0x0 0x0 0x0 0x10 
0x0 0x0 0x40 0xb1 0x0 0x40 0x0 0x0 0x0 0x0 0x0 0x15 
0x0 0x0 0x0 0x67 0x0 0x0 0x0 0x11 0x0 0x0 0x0 0x1f 
0x0 0x0 0x0 0xa2 0x10 0x0 0x0 0x0 0x0 0x0 0x0 0x19 
0x0 0x0 0x40 0xb1 0x0 0x40 0x0 0x64 0x0 0x0 0x0 0x29 

写入后,他们(不正确的,不应该是不同的):

0xb1 0x0 0x0 0x0 0x2c 0x0 0x40 0x0 0x0 0x0 0x0 0x0 
0xa3 0x0 0x0 0x0 0x20 0x0 0x0 0x10 0x5 0x0 0x0 0x0 
0xb1 0x40 0x0 0x0 0x38 0x0 0x40 0x0 0xb 0x0 0x0 0x0 
0xa1 0x0 0x0 0x0 0x14 0x0 0x40 0x0 0x10 0x0 0x0 0x0 
0xb1 0x40 0x0 0x0 0x0 0x0 0x40 0x0 0x15 0x0 0x0 0x0 
0x67 0x0 0x0 0x0 0x11 0x0 0x0 0x0 0x1f 0x0 0x0 0x0 
0xa2 0x0 0x0 0x0 0x0 0x0 0x0 0x10 0x19 0x0 0x0 0x0 
0xb1 0x40 0x0 0x0 0x64 0x0 0x40 0x0 0x29 0x0 0x0 0x0 

我只是无法包裹我的头,因此任何帮助都将非常感谢!

+1

欢迎来到Stack Overflow。请尽快阅读[关于]和[问]页面。数据结构是什么样的?我们需要知道这一点。另请阅读如何创建MCVE([MCVE])。 –

+1

所以你想看看编写代码和读取数据呢?同时使'0x%x'成为'0x%02x'。 – alk

+2

看起来像一个大的endian vs小端的问题。我们需要更多信息, 特别是[MCVE]会有帮助,但是'memcpy'绝对不会混淆任何东西。问题在别处。 –

回答

-3

好吧,你们完全撒谎约memcpy没有搞乱我的数据。在做了一些研究之后,我发现这是一个末端的事情,它颠倒了我32位对象模块的符号表部分中每个4字节块的字节顺序。所以我写了一个小函数来解决它:

/// Flips the bytes in each 4 byte block after the endian flip caused by memcpy 
/// @param - the array of bytes 
/// @param - the length of the array in bytes 
/// 
void flip_bytes(uint8_t byte_array[], int length){ 

    uint8_t tmp; 
    for(int i = 0; i < length; i++){ 
      if((i+1) % 4 == 0){ 

        // switch the first and last bytes 
        tmp = byte_array[i]; 
        byte_array[i] = byte_array[i-3]; 
        byte_array[i-3] = tmp; 
        // switch the middle 2 bytes 
        tmp = byte_array[i-1]; 
        byte_array[i-1] = byte_array[i-2]; 
        byte_array[i-2] = tmp; 
      } 
    } 
} 
+4

本身,正确使用'memcpy()'不会搞乱任何东西。你没有提供足够的信息让任何人知道你的问题是什么,您在此答案中未提供足够的信息来说明您在何处以及如何使用此功能;你对'完全撒谎'的说法是不合理的。你可能有调用未定义行为的代码。由于你没有提供[MCVE],所以很难确定,但是由于编码不稳定而出现不稳定的行为。如果使用正确(例如,内存的源区域和目标区域可能不重叠),则可以使用'memcpy()'。 –

+3

Downvoting这个答案,因为它是误导。建议'memcpy'能够识别endian,并以不同的顺序向源写入字节,这显然是不正确的。你可能遇到的是源数据本身使用与你期望的不同的字节顺序。这是一个数据格式问题,与'memcpy'无关。 – paddy

+0

你不应该采取消极的反馈。如果答案包含错误信息,那么它可能会损害未来的读者,应该指出。 – user694733