Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/c/63.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_Pointers_Struct - Fatal编程技术网

C 在指针指向的地址处创建结构

C 在指针指向的地址处创建结构,c,pointers,struct,C,Pointers,Struct,我有一个unsigned char*head,它指向内存中的某个addess,现在我必须创建一个typedef结构,我已经声明从该指针的位置开始…我不知道该怎么做 这是typedef的声明 typedef struct { struct block *next; struct block *prev; int size; unsigned char *buffer; } block; 我的任务是实现malloc,所以我不能使用malloc。块是free_列表的

我有一个
unsigned char*head
,它指向内存中的某个addess,现在我必须创建一个typedef结构,我已经声明从该指针的位置开始…我不知道该怎么做

这是typedef的声明

 typedef struct {
    struct block *next;
    struct block *prev;
    int size;
    unsigned char *buffer;
} block;
我的任务是实现malloc,所以我不能使用malloc。块是free_列表的一部分,该列表包含程序堆中的所有可用内存块块。因此,上一个和下一个指针指向上一个和下一个可用内存块

Head指向自由列表的开头。当我必须拆分第一个空闲内存块以满足需要更少空间的malloc()请求时,我需要移动头部并在那里创建一个新的块结构

希望这是有意义的。如果不是,那么作业看起来像

上面假设head有足够的空间来存储block的实例。 它所做的是创建一个块,并将内存复制到磁头的位置,然后释放分配的块。

来自注释:

head
指向内存中一个可以覆盖数据的位置的开始……您可以假设我有足够的空间

然后,要获得正确类型的指针:

struct block *p = (struct block *)head;
并获得该区块的副本:

struct block b = *(struct block *)head;

操作系统将提供一个API调用来分配
malloc
可以分割并提供给调用方的内存块。在Linux/unix中,请查看。在Windows中,查看Win32堆API。您的记录将指向此块。确保块的两个分配部分没有重叠是分配器代码的任务

看起来您的记录正在实现一个免费列表。那么,在还没有分配器的情况下,如何分配列表节点呢?通常的解决方案是在空闲块中自己执行。因此,自由块具有以下结构:

typedef struct free_block {
    struct free_block *next, *prev;
    size_t size;
    unsigned char buffer[1];
} FREE_BLOCK;
现在这个数据结构实际上位于空闲块的开始。它的缓冲区在声明中只有1个字节,但实际的缓冲区是
size
bytes。最初,您会有如下内容:

static FREE_BLOCK *free_list = sbrk(ARENA_SIZE);
free_list->next = free_list->prev = free_list;
free_list->size = ARENA_SIZE - offsetof(FREEBLOCK, buffer);
这将整个竞技场作为一个区块放在免费列表上。您的分配器将搜索
free_list
以找到足够大的块,切出所需的块,将剩余的小块(如果有)放回free list。对于释放,它会将释放的块添加到列表中,并合并相邻块

简单自由列表分配器在选择自由块进行分配的方式上有所不同:第一次拟合、旋转第一次拟合、最佳拟合、最差拟合等。在实践中,旋转第一次拟合的效果似乎与其他方法一样好或更好

顺便说一句,所有用自由列表实现的通用算法都不需要双链接。单人的就行了


由于这是一项学术任务,因此只需调用
malloc
(而不是操作系统API)就可以建立分配器将管理的大块(通常称为“竞技场”)。您还可以声明一个大的字节数组。

您的结构没有标记,因此您需要为它指定一个以便它指向自身:

 typedef struct block {
    struct block *next;
    struct block *prev;
    int size;
    unsigned char *buffer;
} block;
如果您使用的是C99,您可以在必要时直接初始化
头部的内存,而无需声明临时
结构块

*(block *)head = (block){NULL, NULL, 0, NULL};
您现在在地址
头部有一个
struct块
,只要您正确地转换它

e、 g

或者为其指定强制转换指针:

block *p = (block *)head;
p->size = 5;

所以你有一个
无符号字符*
,你知道它实际上是一个
块*
,你想访问
?你确定某个地址的分配属于你的应用程序吗?是的,我刚刚分配了它!将其转换为block*x=(block*)头@Georges,你给它分配了正确的尺寸,即sizeof(块)?为什么现在它是一个无符号字符*?他仍然需要知道它需要足够的空间来存储大小(块)的内存,以避免任何seg故障或错误。赋值的目的是实现malloc(),因此我不应该使用malloc()。这些信息在问题描述中会很有用:P@Magtheridon96:不是副本。。。b变成了一个结构存取器。我不明白b现在是如何在位置和头部保存块结构的。@lhsan Docs。我在谷歌上找不到“结构化访问器”这个表达式。你的意思是如果我写
b.member=42那么在原始结构中,它也将更改为42?因为它不会。@GeorgesKrinker它不会。它与另一个地址的
*head
内容相同。struct block b=*(struct block*)head;意思是:符号b作为结构块访问head指向的内存内容。所以修改b会修改头部的任何东西。。。b、 成员=头->成员
((block *)head)->size = 5;
block *p = (block *)head;
p->size = 5;