gpt4 book ai didi

c - 使用灵活数组成员的奇怪行为

转载 作者:太空宇宙 更新时间:2023-11-04 03:02:43 27 4
gpt4 key购买 nike

我尝试使用更广为接受的惯用语将结构的 void* 成员替换为灵活的数组成员:

typedef struct Entry {
int counter;
//void* block2; // This used to be what I had
unsigned char block[1];
}

然后我将条目添加到一个连续的内存块中:

void *memPtr = mmap(NULL, someSize*1024, PROT_READ|PROT_WRITE, 
MAP_PRIVATE|MAP_ANONYMOUS, -1, 0);

这样:

int number = 0;

int AddEntry(void *data) {
Entry *entry;
entry = malloc(sizeof(Entry) + ((SECTOR_SIZE-1) * sizeof(unsigned char));
entry->counter = 1;
memcpy(entry->block, data, SECTOR_SIZE);

// make sure number doesn't overflow space, etc...
memcpy(&memPtr[number], entry, sizeof(Entry) + ((SECTOR_SIZE-1) * sizeof(unsigned char));
number++;
return 0;
}

问题是在我需要时解压这些数据。例如,如果我这样做:

void * returnBlock(int i) {
Entry * entry = &memPtr[i];
printf("Entry counter is %d\n", entry->counter); // returns 1, reliably
return entry->block; // Gives me gibberish but not if I uncomment void* block2.
}

这有什么原因吗?我不一定认为我在任何地方踩东西,它曾经使用 void* 方法。 奇怪的是,如果我将一个虚拟的 void* 放回结构中,它会起作用。如果我输入一个虚拟 int,它就不起作用。

编辑:实际上,如果 AddEntry 中的 number 不为 0,它也会失败。如果有的话,我踩到了什么?

最佳答案

你的问题在这里:

&memPtr[number]

因为 memPtr 是一个 void * 指针,这在 C 中实际上是完全不允许的。一些编译器确实允许对 void * 指针进行算术运算作为语言扩展 - 但是他们将其视为一个 char * 指针。

这意味着 &memPtr[number] 可能仅将 number bytes 索引到您的内存块中 - 所以第二个 Entry 复制进来的结构会覆盖第一个,依此类推。

您的分配行似乎假设每个 Entry 有 1024 个字节(如果 someSize 是多个 Entry 结构),所以您可能想要像这样的东西:

((char *)memPtr + number * 1024)

(与 returnBlock() 函数类似)。

但是,如果您这样做,您会注意到使用灵活数组成员没有意义 - 因为您正在创建这些结构的连续数组,并且没有单独的索引,所以您必须假设每个一种是固定尺寸。这意味着您不妨将每个都设置为固定大小:

typedef struct Entry {
int counter;
unsigned char block[1024 - sizeof counter];
}

关于c - 使用灵活数组成员的奇怪行为,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/9459675/

27 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com