簡體   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