C中的结构实际上如何与malloc一起使用

时间:2018-08-12 05:56:29

标签: c c99

我正在尝试创建一个程序,该程序包含一个名为“ myStruct”的结构,该结构包含一个字符串数组“ char * array”。然后是分配内存的函数,然后打印输出,然后是如下所示的主要函数:

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

typedef struct myStruct { char *array; } str1;

void display(str1 *p1) {
  char *array;
  array = (char *)malloc(10 * sizeof(char));
  printf("%s", p1->array);
  free(array);
}

int main(void) {
  str1 s1;
  strcpy(s1.array, "Damn");
  return 0;
}

但是我希望输出“ Damn”,但是输出却什么也没有。 但是,在编译过程中,显示​​以下警告:

user@localhost: ~ $ clang struct.c -Weverything
struct.c:7:6: warning: no previous prototype for function 'display' [-Wmissing-prototypes]
void display(str1 *p1) {
     ^
1 warning generated.

这意味着未调用函数。在这种情况下,我在语法和语义上都需要一些帮助。我不确定如何调用函数display()。

3 个答案:

答案 0 :(得分:2)

您没有在display中呼叫main()。要将内存分配给char *array并复制字符串,可以设计如下函数:

#define DEFAULT_LEN 10
void allocate(str1 *p1, const char * str) {
    char * array;
    if(str) {
        //(char *) is omittable in C (not C++)
        array = malloc(strlen(str) + 1);
        strcpy(array, str);
    }
    else {
        array = malloc(DEFAULT_LEN);
        array[0] = 0;
    }
    p1->array = array;
}

,您可以这样打印文本:

int main() {
    str1 s1; allocate(&s1, "Damn");
    puts(s1.array);
    deallocate(&s1);
    return 0;
}

您必须释放内存:

void deallocate(str1 *p1) {
    free(p1->array);
    p1->array = NULL;
}

答案 1 :(得分:1)

使用str1 s1 s1在堆栈上分配时,其中的数组只是一个指针,没有为其内容分配内存。

strcpy然后尝试写入该指针指向的任何位置,该值可能为零,也可能是随机数,具体取决于您的编译器及其设置。

您需要先为字符串分配一个缓冲区,例如:

str1 s1;
size_t len = strlen("Damn");
s1.array = malloc((len+1) * sizeof(char)); // +1 for the null terminator
strcpy(s1.array, "Damn");

答案 2 :(得分:1)

让我们看看我们是否能为您提供一些基础。声明s1时,将声明类型struct myStruct的结构,该结构方便地具有typedefstr1;声明:

str1 s1;

s1创建存储,该存储具有自动存储持续时间,并且仅在s1处于范围内时才有效。 s1的自动存储包括一个指针 array的存储,仅此而已。 (暂时忽略填充)。 一个指针 array完全是未初始化的,它指向一些您无法写入的不确定地址。尝试写入未初始化的值将调用未定义行为,并且程序的有效操作将在此时停止。 (实际上,尝试对其进行写操作可能会导致分段错误)

如何为s1.array创建存储?这是您需要分配的位置。 (之前,您尝试复制到s1.array)存储字符串需要多少内存? strlen(string) + 1(为 nul-终止字符提供存储的+1)

知道这一点,并按照我在评论中留下的链接,您可以使用以下方式为字符串分配存储空间:

s1.array = malloc (strlen ("Damn") + 1);

对于每个分配,您将验证分配成功,然后再尝试使用内存块。如果malloc失败(并且确实如此),则您尝试使用无效块将使您回到原本无法分配的状态–逐步进入未定义行为 ...

现在您已经初始化s1.array指向有效的内存块,并且验证分配成功,现在可以将字符串复制到s1.array

strcpy (s1.array, "Damn");

您的display函数不需要进行任何分配(当然可以)。您的display函数仅需要显示现在保存在s1.array中的字符串。正如乔纳森·莱夫勒(Jonathan Leffler)所述,您只需将指针传递到display(str1 *s),然后从内部输出s->array。没什么比:

void display (mystruct_t *s)
{
    printf ("%s\n", s->array);
}

您将通过main()呼叫的方式为:

     display (&s);           /* pass the address of s (a pointer to s) */

在您编写的任何动态分配内存的代码中,对于任何分配的内存块,您都有2个职责:(1)始终保留指向起始地址的指针因此,(2)当不再需要它时可以释放

display()返回时,s1.array的使用已结束,可以释放它。立即养成释放分配的内存的习惯,不要仅仅依赖于程序结束时就释放它-随着代码变得更加复杂,这将带来很多好处。

    free (s1.array);         /* if you allocate it, you free it when done */

由于s1具有自动存储功能,因此该结构本身没有任何可用空间。

让我们举两个例子。第一个将声明具有自动存储持续时间的结构,并且仅分配给s.array(如上所述)。第二个将声明一个指向您的结构的指针,现在需要您为结构和数组分配。 (这又需要您释放数组和结构)

具有自动存储期限的结构

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

#define STR "Damn"

typedef struct mystruct { 
    char *array;
} mystruct_t;

void display (mystruct_t *s)
{
    printf ("%s\n", s->array);
}

int main (void) {

    mystruct_t s;       /* struct with automatic storage - for the pointer */

    /* s is a struct, so you use the '.' operator access members */
    s.array = malloc (strlen (STR) + 1);    /* you must allocate for array */
    if (s.array == NULL) {                  /* validate each allocation */
        perror ("malloc-s.array");
        return 1;
    }
    strcpy (s.array, STR);  /* with valid memory pointed to, you can copy */

    display (&s);           /* pass the address of s (a pointer to s) */

    free (s.array);         /* if you allocate it, you free it when done */

    return 0;
}

声明要构造的指针

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

#define STR "Damn"

typedef struct mystruct { 
    char *array;
} mystruct_t;

void display (mystruct_t *s)
{
    printf ("%s\n", s->array);
}

int main (void) {

    mystruct_t *s;          /* declare a pointer to the struct itself */

    s = malloc (sizeof *s); /* now you must allocate for the struct */
    if (s == NULL) {        /* and you validate every allocation */
        perror ("malloc-s");
        return 1;
    }

    /* s is a pointer to struct, so you use -> to reference member */
    s->array = malloc (strlen (STR) + 1);   /* you must allocate for array */
    if (s->array == NULL) {                 /* validate each allocation */
        perror ("malloc-s->array");
        return 1;
    }
    strcpy (s->array, STR); /* with valid memory pointed to, you can copy */

    display (s);            /* s is a pointer, just pass it to display */

    free (s->array);        /* if you allocate it, you free it when done */
    free (s);               /* don't forget to free the struct */

    return 0;
}

(在两种情况下,输出只是您的字符串)

请仔细检查两者,以注意使用'.'->运算符来取消引用结构并访问array。您需要了解何时以及在何处使用它们。

如果您还有其他问题,请告诉我。