使用C中的char指针创建,返回和转换结构

时间:2016-11-20 04:32:46

标签: c pointers struct malloc

我很难用结构来记住C规则。基本上,我有一个像这样的结构:

typedef struct {
    char* ptr;
    int size;
} Xalloc_struct;

char* ptr最多只能是一个字符

在我的程序中,我必须使用自己的函数将内存分配并释放到假磁盘(全局声明为char disk[100];):

char disk[100];

void disk_init() {
    for(int i = 0; i < 100; ++i) {
        disk[i] = memory[i] = 0;
    }
}

struct Xalloc_struct* Xalloc(int size) {
    // error checking
    // ...
    // run an algorithm to get a char* ptr back to a part of the global disk
    // array, where index i is the index where content at disk[i] starts
    char* ptr = &disk[i];
    struct Xalloc_struct *ret = malloc(sizeof(struct Xalloc_struct));
    ret->size = size;
    ret->ptr = malloc(sizeof(char));
    ret->ptr = ptr;
    return ret;
}

int Xfree(void* ptr) {
    struct Xalloc_struct* p = (struct Xalloc_struct*) ptr;
    int size = p->size;
    int index = *(p->ptr);
    // .. more stuff here that uses the index of where p->ptr points to
    free(p->ptr);
    free(p);
    return 0;
}

int main() {
    disk_init();
    struct Xalloc_struct* x = Xalloc(5);
    Xfree(x);
    return 0;
}

当这个编译时,我会遇到很多错误:

 error: invalid application of ‘sizeof’ to incomplete type ‘struct Xalloc_struct’
     struct Xalloc_struct *ret = malloc(sizeof(struct Xalloc_struct));
                                               ^

error: dereferencing pointer to incomplete type
     ret->size = size;
        ^

error: dereferencing pointer to incomplete type
         free(x->ptr);
               ^
 error: dereferencing pointer to incomplete type
     int size = cast_ptr->size;
                        ^
error: dereferencing pointer to incomplete type
     int free_ptr = *(cast_ptr->ptr);
                              ^

那么,我应该如何分配和解除分配这些结构?我如何修改/编辑它们包含的内容?

2 个答案:

答案 0 :(得分:2)

第一个问题是Xalloc_struct是一个类型,而不是结构的名称。你用这个声明了这个类型:

typedef struct {
    char* ptr;
    int size;
} Xalloc_struct;

typedef的格式为typedef <type name or struct definition> <name of the type>。因此,您将类型Xalloc_struct声明为struct { char *ptr; int size; }

这意味着您可以像使用任何其他类型名称一样使用它:Xalloc_struct somevar = ...;

您是否使用名称声明了结构...

struct Xalloc_struct {
    char* ptr;
    int size;
};

然后就像你一样struct Xalloc_struct somevar = ...;

为数组分配内存时的经验法则(char *是一个字符数组)是您分配sizeof(type) * number_of_items。字符数组以空字节结束,因此对于它们,您还需要一个字符。

Xalloc_struct *ret = malloc(sizeof(Xalloc_struct));
ret->ptr = malloc(sizeof(char) * num_characters+1);

但如果您只存储一个字符,则不需要一个字符数组。只需存储一个角色。

typedef struct {
    char letter;
    int size;
} Xalloc_struct;

Xalloc_struct *ret = malloc(sizeof(Xalloc_struct));
ret->letter = 'q';  /* or whatever */

但我认为你真正在做的是存储指向disk数组中某个点的指针。在这种情况下,你根本不需要malloc。您只需将指针存储为任何其他指针。

typedef struct {
    char* ptr;
    int size;
} Xalloc_struct;

Xalloc_struct *ret = malloc(sizeof(Xalloc_struct));
ret->ptr = &disk[i];

然后您可以使用ret->ptr[0]读取该字符。

由于你没有分配ret->ptr,所以不要释放它!这会导致崩溃,因为disk位于堆栈内存中并且无法自由运行。如果它在堆内存(即malloc)中,它可能也会崩溃,因为它会尝试在分配的块中间释放。

void Xalloc_destroy(Xalloc_struct *xa) {
    free(xa);
}

以下是我的表现。

#include <stdio.h>
#include <stdlib.h>

char disk[100] = {0};

typedef struct {
    char *ptr;
    int idx;
} Disk_Handle_T;

static Disk_Handle_T* Disk_Handle_New(char *disk, int idx) {
    Disk_Handle_T *dh = malloc(sizeof(Disk_Handle_T));
    dh->idx = idx;
    dh->ptr = &disk[idx];

    return dh;
}

static void Disk_Handle_Destroy( Disk_Handle_T *dh ) {
    free(dh);
}

int main() {
    Disk_Handle_T *dh = Disk_Handle_New(disk, 1);

    printf("%c\n", dh->ptr[0]);  /* null */

    disk[1] = 'c';
    printf("%c\n", dh->ptr[0]);  /* c */

    Disk_Handle_Destroy(dh);
}

答案 1 :(得分:1)

你试图完成的事情有点令人困惑,但从语法的角度来看,你的主要问题是将typedef视为一个正式的结构声明,而不是为你的Xalloc函数提供索引信息,以及在ret->ptr中已经有指针和存储的地方分配disk

首先,除非您指定指针,否则取消引用运算符'*'将使用变量,而不是类型。 e.g。

Xalloc_struct *Xalloc (...)

Xalloc_struct* Xalloc (...)

为什么呢?为了避免使用指针 type (没有指针类型只是 type )声明某些内容的不正确外观,例如:

int* a, b, c;
上面的

bc肯定不是指针类型,但是通过将'*'附加到类型,看起来好像是在尝试声明变量int*(不正确)。

int *a, b, c;

让你更明确地想要在a和两个整数bc中声明一个指向int 的指针。

接下来,在Xfree中,您可以(但通常不希望)将指针类型指定为int(存储大小问题等)(例如int index = *(p->ptr);)如果你需要一个指针的引用,使用指针。如果你想要指针本身的地址,请确保你使用的类型足够大,以适应硬件上的指针大小。

为什么要为ret->ptr = malloc(sizeof(char));分配存储空间?您已在char disk[100];中拥有存储空间您无法从分配中获益。只需将disk中元素的地址分配给ptr(指针可以保存指针而无需进一步分配)如果您打算使用内存,则只需要为ret->ptr分配存储空间分配,例如将字符串或多个字符复制到分配给ret->ptr的内存块。 ret->ptr可以在data中存储元素的地址,而无需进一步分配。 (它不清楚你到底想要什么)

您可以自由使用typedef,实际上这是一种很好的做法,但是当您指定typedef时,它不等同于,也不能用作命名结构。这就是你的不完整类型问题出现的地方。

总而言之,您似乎尝试执行类似以下操作:

#include <stdio.h>
#include <stdlib.h>

typedef struct {
    char* ptr;
    int size;
} Xalloc_struct;

char disk[100] = "";

Xalloc_struct *Xalloc (int size, int i) {
    char *ptr = &disk[i];
    Xalloc_struct *ret = malloc (sizeof *ret);
    ret->size = size;
    // ret->ptr = malloc (sizeof *(ret->ptr)); /* you have a pointer */
    ret->ptr = ptr;
    return ret;
}

int Xfree (void *ptr) {
    Xalloc_struct *p = (Xalloc_struct *) ptr;
    // int size = p->size;    /* unused */
    // int index = *(p->ptr); /* what is this ?? */
    // .. more stuff here that uses the index of where p->ptr points to
    // free (p->ptr);
    free (p);
    return 0;
}

int main (void) {

    int i = 0;
    Xalloc_struct *x = Xalloc (5, i++);
    Xfree(x);

    return 0;
}

查看typedef的使用方式的不同,如果您有任何疑问,请告诉我。