2015-06-23 113 views
1

我具有以下结构:包结构/避免填充

struct SkipListNode{ 
    void  *data;  // 8 bytes 
    uint8_t  size;  // 1 byte 
    // 7 bytes padding here... 
    void  *next[1]; // dynamic array, 8 bytes each "cell" 
}; 

我使用malloc()和我比sizeof(SkipListNode)分配更多的空间,所以我延伸next[]阵列。

我想避免7 bytes浪费。我可以完全删除大小字段,但是我应该在数组末尾保留单个NULL(8个字节)。但是这不会减小尺寸。

我应该用__ attribute__((__ packed__))还是有一些不同的方法可以做到这一点?

这也必须在C和C++下编译。

编译器是gcc。

+0

'attribute((packed))'有什么问题?内存是否只关心,你是否创建了这种类型的很多实例(对象)? –

+0

一般,没问题。内存是关注点,因为我制作了成千上万个这样的(它是跳过列表节点) – Nick

+2

你认为'#pragma pack(1)' –

回答

2
#include <stdio.h> 
#include <stdint.h> 

struct SkipListNode{ 
    void  *data;  // 8 bytes 
    uint8_t  size;  // 1 byte 
    void *next[1]; 
    }; 

struct SkipListNode_pack{ 
    void  *data;  // 8 bytes 
    uint8_t  size;  // 1 byte 
    void *next[1]; 
    } __attribute__((packed)); 

int main(int argc, char** argv) 
{ 
    printf("%d:%d\n", sizeof(struct SkipListNode), sizeof(struct SkipListNode_pack)); 
    return 0; 
} 

从上面的代码的输出:
[email protected] sandbox]$ ./test
24:17

所以是的,你一定要,如果你想节省内存使用__attribute__((packed))你的情况。另一方面,就像@MarioTheSpoon说的那样 - 它可能会带来性能损失。

我会检查填充解决方案,看看您是否可以在特定机器上忍受这种惩罚。我敢打赌,除非你真的关键性能,否则你甚至不会注意到它。

+0

我也不同意!只有在确实需要时才使用#pragma pack(1)。在标准计算机上浪费大约100k的标准程序应该不是最令人担忧的问题。当然,如果它是某种嵌入式系统,或者您正在分配数百万条这样的记录,推理可能会有所不同。系统再次欺骗你,因为malloc将再次对齐64位边界上的缓冲区(在所描述的系统上)。 –

+1

为什么你根据OP的'struct'忽略'next'成员有什么特别的理由? – alk

+0

@alk相应地修复了我的答案,谢谢! –

0

我接受了对方的回答,

但是,我也认为是程序的重构,我发现了一种能正确进行,不知道该数组的大小。

如果有人有兴趣在这里它是:
https://github.com/nmmmnu/HM3/blob/master/skiplist.cc

所以我消除了size领域,我消除结束NULL。现在结构是对齐的:)

虽然重构,我记得可以使用malloc_usable_size()找到分配块的大小。这是沉重的非便携式黑客攻击,但在其他一些情况下可以很好地工作。