繁体   English   中英

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

[英]Creating, returning, and casting a struct with a char pointer in C

我很难记住带有结构的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);
                              ^

因此,我应该如何分配和取消分配这些结构? 以及如何修改/编辑它们包含的内容?

第一个问题是Xalloc_struct是类型,而不是结构名称。 您通过以下方式声明了该类型:

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

typedef的形式为typedef <type name or struct definition> <name of the type> 因此,您将Xalloc_struct类型Xalloc_structstruct { char *ptr; int size; } struct { char *ptr; int size; } 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);
}

您试图完成的工作有点令人困惑,但是从语法的角度来看,您的主要问题是将typedef视为正式的结构声明,而不是为Xalloc函数提供索引信息,并在其中分配ret->ptrdisk已经有一个指针和存储了。

首先,顺便说一句,当您指定指针时,取消引用运算符'*'变量一起使用 ,而不与type一起使用 例如

Xalloc_struct *Xalloc (...)

Xalloc_struct* Xalloc (...)

为什么? 为了避免用指针类型声明某些内容的不当外观(在没有指针类型的情况下,只需键入即可 ),例如:

int* a, b, c;

bc以上是最肯定不是指针类型,而是通过附加'*'为,如果你想声明的变量,它出现在类型 int* (这是不正确的)。

int *a, b, c;

更清楚地表明,您打算在a和两个整数bc声明一个指向int类型指针

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

为什么要为ret->ptr = malloc(sizeof(char));分配存储空间ret->ptr = malloc(sizeof(char)); 您已经在char disk[100];存储了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使用方式的差异,如果您有任何疑问,请告诉我。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM