Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/c/68.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/0/laravel/10.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C 如何在成对结构中便携保存两个单词的内存?_C_Bit Manipulation_Pointer Arithmetic - Fatal编程技术网

C 如何在成对结构中便携保存两个单词的内存?

C 如何在成对结构中便携保存两个单词的内存?,c,bit-manipulation,pointer-arithmetic,C,Bit Manipulation,Pointer Arithmetic,我有一个总是成对出现的数据结构struct foo。现在,每个struct foo都携带一个指向另一个struct foo的指针: struct foo { struct foo *other_half; /* ... */ }; 由于我的程序需要很多(>1'000'000)struct foo,因此我迫切希望减少每个程序的大小。有没有办法去掉另一半指针,并通过其他方法找到一对结构foo的另一半?考虑一个数组结构foo[2]两个结构foo对齐到2*sizeof(struct f

我有一个总是成对出现的数据结构
struct foo
。现在,每个
struct foo
都携带一个指向另一个
struct foo
的指针:

struct foo {
    struct foo *other_half;
    /* ... */
};

由于我的程序需要很多(>1'000'000)
struct foo
,因此我迫切希望减少每个程序的大小。有没有办法去掉
另一半
指针,并通过其他方法找到一对
结构foo
的另一半?

考虑一个数组
结构foo[2]
两个
结构foo
对齐到
2*sizeof(struct foo)
或更大。请注意,
foos[0]
2*sizeof(struct foo)
或更大的值对齐,而
foos[1]
仅与
sizeof(struct foo)
对齐。您可以使用该信息来确定指向此类对齐的
struct foo[2]
的随机
struct foo*
是否指向第一个或第二个成员

要获得充分对齐的内存,请编写自定义分配器或使用C11
aligned\u alloc
函数。请注意,实际上并不需要完全对齐内存,只需清除我们在
other_half
中测试的位就足够了

一个简单的函数实现,在给定一个指向另一半的指针的情况下,查找一对
struct foo
的另一半,如下所示:

struct foo *other_half(struct foo *half) {
    if ((uintptr_t)half % (2 * sizeof *half) == 0)
        return half + 1;
    else
        return half - 1;
}

但是,如果
sizeof(struct foo)
不是二的幂,则此函数的效率不是很高,因为它涉及缓慢的模运算。为了加快速度,考虑代码< > siZeof(StultFoO)< /C> >,其形式为2n·q。很容易看出,检查
((uintptpr_t)half&(uintptpr_t)1就足够了,这是一种具有较少技巧的替代设计,但每个
foo
使用单字节;如果将值与其他字段打包在一起,则使用位

#include 
#include 

struct foo {
    char Index; // can be packed together with some other field
    /* ... */
};

typedef struct foo pair[2];

void init_pair(pair *p){
    for(size_t i = 0; i < sizeof(*p); i++){
        (*p)[i].Index = (char)(i);
    }
}

struct foo *pair_index(struct foo *piece, size_t index){
    return &piece[index - (size_t)piece->Index];
}

struct foo *pair_other(struct foo *piece){
    return pair_index(piece, piece->Index ^ 0x01);
}

遗憾的是,由于所有结构成员都是指针,因此无法提供额外的位。我的意思是,我可以重新利用其中一个指针的最低有效位,但由于指针没有指向它们应该指向的位置,这使得调试代码成了一件非常麻烦的事。执行这种对齐技巧似乎更简单。向结构添加额外的标志是不可能的还有一个问题。整个问题都是关于节省内存,添加更多数据不会减少内存。根据具体情况,对齐的内存可能会浪费/分割内存,例如,如果您需要用3个字节填充以使事情对齐。如果所有字段都是指针,并且在x64上,那么您(可能)也在浪费内存。(注意:我不是说这是一个错误。)“更好”的解决方案,只是一种可进行不同权衡的替代设计)我不是在浪费内存。请再次阅读技巧,这对数组中的一部分总是具有较高的对齐度,因此,如果使用自定义内存池,则在提供结构的大型数组中,最多只需丢弃一个条目。请注意,在C中,每个结构都包含隐式填充,以其最小对齐度乘以design(因此数组可以正常工作)使您的观点变得毫无意义。您能否通过提供第一个结构的奇偶校验来避免对齐要求?如果设置了
half&-sizeof(*half)&sizeof(*half)
(half+1)&-sizeof(*half)&sizeof(*half)
不是,反之亦然。因此它们是交替的,如果它们所在的块对齐,则块中的第一个结构将不设置该位。如果块中的第一个结构设置了该位,则可以翻转条件。@hacatu是,这就是为什么我说:“请注意,实际上并不需要将内存完全对齐,只需清除另一半中测试的位就足够了。”
#include 
#include 

struct foo {
    char Index; // can be packed together with some other field
    /* ... */
};

typedef struct foo pair[2];

void init_pair(pair *p){
    for(size_t i = 0; i < sizeof(*p); i++){
        (*p)[i].Index = (char)(i);
    }
}

struct foo *pair_index(struct foo *piece, size_t index){
    return &piece[index - (size_t)piece->Index];
}

struct foo *pair_other(struct foo *piece){
    return pair_index(piece, piece->Index ^ 0x01);
}
int main(int argc, char const *argv[])
{
    pair p;
    init_pair(&p);

    struct foo *first = &(p[0]);
    struct foo *second = &(p[1]);

    printf("%p %p\n", pair_index(first, 0), pair_index(first, 1));
    printf("%p %p\n", pair_index(second, 0), pair_index(second, 1));
    printf("%p %p\n", pair_other(second), pair_other(first));
    return 0;
}