[英]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.