[英]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_struct
为struct { 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->ptr
在disk
已经有一个指针和存储了。
首先,顺便说一句,当您指定指针时,取消引用运算符'*'
与变量一起使用 ,而不与type一起使用 。 例如
Xalloc_struct *Xalloc (...)
不
Xalloc_struct* Xalloc (...)
为什么? 为了避免用指针类型声明某些内容的不当外观(在没有指针类型的情况下,只需键入即可 ),例如:
int* a, b, c;
b
和c
以上是最肯定不是指针类型,而是通过附加'*'
为,如果你想声明的变量,它出现在类型 int*
(这是不正确的)。
int *a, b, c;
更清楚地表明,您打算在a
和两个整数b
和c
声明一个指向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.