将一块内存块的前两个字节设置为指针或NULL,同时仍然访问块的其余部分

时间:2010-04-27 18:39:14

标签: c pointers

假设我有一块内存:

void *block = malloc(sizeof(void *) + size);

如何设置指向块开头的指针,同时仍能访问剩余的保留空间?出于这个原因,我不想简单地将'block'分配给另一个指针或NULL。

6 个答案:

答案 0 :(得分:4)

  

如何将块的前两个字节设置为NULL或将其指向某个位置?

除非您在16位计算机上运行,​​否则这没有任何意义。

根据您调用malloc()的方式,您计划让前N个字节成为指向其他内容的指针(其中N可能是2,4或8,具体取决于您是否'重新运行在16位,32位或64位架构上。这是你真正想做的吗?

如果是,那么你可以创建一个指针到指针的方法(认识到你实际上不能使用void *来改变任何东西,但我不想通过引入真实来混淆事物型):

void** ptr = block;

但是,用结构定义块会更加优雅(这可能包含语法错误;我没有通过编译器运行它):

typedef struct {
    void* ptr; /* replace void* with whatever your pointer type really is */
    char[1] data; } MY_STRUCT;

MY_STRUCT* block = malloc(sizeof(MY_STRUCT) + additional);
block->ptr = /* something */

答案 1 :(得分:2)

memset(block, 0, 2);

memset可以在string.h

中找到

答案 2 :(得分:1)

将分配的内存块的前两个字节设置为0很容易。有很多方法可以做到,例如:

((char*)block)[0] = 0;
((char*)block)[1] = 0;

现在,提问的方式显示出一些误解。

您可以在分配的块的前两个字节中放置任何内容,它不会更改任何内容以访问以下字节。唯一的区别是C字符串操作运算符用作字符串以0字节结尾的约定。然后,如果您执行strcpy((char*)block, target)之类的操作,如果第一个字节为零,它将立即停止复制。但你仍然可以做strcpy((char*)block+2, target)

现在,如果你想将指针存储在块的开头(通常不是2个字节)。 您可以执行与上面相同的操作,但使用void *而不是char。

((void**)block)[0] = your_pointer;

您可以根据需要访问剩余的块,只需获取它的地址然后继续。你可以用例如。

来做
void * pointer_to_rest = &((void**)block)[1];
PS:我不推荐这样的指针游戏。它们非常容易出错。你最好的举动可能是遵循@Anon提出的struct方法。

答案 3 :(得分:0)

void *block = malloc(sizeof(void *) + size); // allocate block
void *ptr = NULL; // some pointer
memcpy(block, &ptr, sizeof(void *)); // copy pointer to start of block

答案 4 :(得分:0)

我猜你要问的是什么,但你的措辞太混乱了,以至于我可能完全错了。我假设你想要一个指向你分配的块的“前2个字节”的指针,然后是另一个指向块其余部分的指针。

指针不带有关于它们指向的内存块大小的信息,因此您可以这样做:

void *block = malloc(sizeof(void *) + size);
void *first_two_bytes = block;
void *rest_of_block = ((char*)block)+2;

现在,first_two_bytes指向您分配的块的开头,您应该将其视为指向2个字节长的内存区域。

并且rest_of_block指向从3个字节开始的块的部分,你应该将它视为指向比你分配的字节小2个字节的内存区域。

但请注意,这仍然只是一次分配,您应该只free block指针。如果你释放所有三个指针,你将破坏堆,因为你将在同一个块上多次调用free

答案 5 :(得分:0)

在使用哈希表实现map接口时,我遇到了类似的问题,其中每个键值对(两者都不是静态大小,省略了定义编译时结构的选项)必须存储在块中堆内存,还包括指向链表中下一个元素的指针(如果在多个哈希值被散列到哈希表数组中的同一索引的情况下,则应该将这些块链接起来)。在块的开头留下指针的空间,我发现了kriss提到的解决方案:

((void**)block)[0] = your_pointer;

将指针作为数组转换为块,然后使用括号语法处理指针算术和解除引用,这是将新值复制到此指针的最干净的解决方案"字段"块。