将堆 space 分配给 C 中自定义数据类型的一个元素

Allocating heap space to one element of custom data type in C

我有以下数据类型:

typedef struct {
    int num;
    char *str;
} NumStr;

和变量 x:

NumStr *x;

如何为 str 指针分配堆 space?我试过了

x->str = (char*)malloc(sizeof(char*));

但它不起作用。

我是 C 的新手,所以如果我遗漏了一些明显的东西,我深表歉意。提前致谢。

NumStr* 这样的指针指向内存中的某处 - 因此您需要在分配给 x->str 之前分配 x:

NumStr* x = malloc(sizeof(*x));.


请注意,您已经完成 no need to cast to (char*) - 不要忘记按特定顺序 free(x->str); 然后 free(x);

你可以简单地做

NumStr x;
x.int = 3;//for example
x.str = malloc(5*sizeof(char));

如果以后需要指向 x 的指针(几乎等同于代码中的 x),只需使用 &x.

我的代码说明:

x 会自动分配到堆栈上,就像 int 一样(如 int x; x = 0;)。之后您可以自由初始化它(如我上面的示例)。 NumStr *x 声明分配 NumStr * 类型的变量,指针,您通常使用 malloc 初始化(如丹尼尔的回答),然后才初始化分配的内存。

(一如既往地使用 -allocs)你需要 free 稍后你自己指向的内存。

再澄清一件事:x->str = (char*)malloc(sizeof(char*)); 应更正为 x->str = malloc(sizeof(char));,可选 x->str = malloc(5*sizeof(char)) 或其他内容。

就您的实际问题而言:

How can I allocate heap space for the str pointer?

您所做的 (x->str = (char*)malloc(sizeof(char*));) 可能不是您想要的。 sizeof(char*) 很可能是 4 或 8,具体取决于您的系统,但更重要的是与 x->str 将指向的 char 对象无关。分配动态内存时,一般范例是从您分配给的左值为类型“向上一级”分配 space,作为 sizeof 该类型和 [ 的数量的组合=87=]想要的。也就是说,对于某些类型 T,您希望按以下方式分配 space:

// pseudo code
T* myPointerToT = malloc(sizeof(T) * numberOfTObjectsIWant);

这里,myPointerToT是一个T指针类型(T*)。 “向上一级”是一种类型 T,因此这就是您要提供给 sizeof 的内容。 T* 类型应该 指向 T 个对象,因此您必须为所需的 T 个对象分配足够的大小。

还有一件事,而不是在 sizeof(T) 中使用 T,首选语法是使用取消引用的变量名。在上面的示例中,这将是 *myPointerToT,将行更改为:

T* myPointerToT = malloc(sizeof(*myPointerToT) * numberOfTObjectsIWant);

此后维护较少的原因。假设 Tchar,一段时间后,它变为 int。我们现在必须在两个地方更改 T

char* myPointerToT = malloc(sizeof(char) * numberOfTObjectsIWant);

更改为

int* myPointerToT = malloc(sizeof(int) * numberOfTObjectsIWant);

而如果我们从

开始
char* myPointerToT = malloc(sizeof(*myPointerToT) * numberOfTObjectsIWant);

我们现在只需要改变一个地方的T:

int* myPointerToT = malloc(sizeof(*myPointerToT) * numberOfTObjectsIWant);

注意,sizeof 是一个编译时运算符,所以 *myPointerToT 并不是真正取消引用任何东西;预处理器可以查看并确定类型,这是 sizeof 需要的。

在你的例子中,x->str 是一个 char* 类型,所以你想为至少一个 char 对象分配 space。

// as stated in another answer, no need to cast malloc return value
x->str = malloc(sizeof(char));
// or
x->str = malloc(sizeof(*(x->str)));

实际上,为单个 char 分配 space 是愚蠢的,正如您的变量名所示,这意味着是一个字符串,因此您需要多个 chars:

x->str = malloc(sizeof(char) * numOfCharsIWant);

另外,C标准定义sizeof(char)为1,所以这个也可以省略:

x->str = malloc(numOfCharsIWant);

最后,只有在“必须”时才应动态分配内存,实际上通常归结为:

  1. 直到运行时您才知道需要多少内存
  2. 您需要“大量”内存。 “很多”的含义取决于您的系统,但根据我的经验,桌面上每个执行线程的默认堆栈大小 linux 是 8MB,这对于日常操作来说足够 space。

如果您大致了解最大字符串大小,则可以绕过动态内存分配,同时执行以下操作:

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

#define MAX_STR_LENGTH 30  // "small enough"

typedef struct {
    int num;
    char str[MAX_STR_LENGTH];
} NumStr;

int main(void)
{
  // a single object, keep it in automatic storage
  NumStr x;

  x.num = 3;
  strcpy(x.str, "hello")

  printf("%d: %s\n", x.num, x.str);

  // no need to clean up dynamically allocated memory, since there is none
  return 0;
}

你用过

x->str = (char*)malloc(sizeof(char*));

但是 sizeof 运算符会给你指针类型本身的大小(这不是你想要的,因为指针已经在结构中分配 space )。如果你想为一个字符串分配 space,比方说,50 个字符,你应该使用

x->str = malloc(50);  /* don't use a cast to convert the pointer type,
                       * malloc already solves that, giving you a 
                       * compatible pointer type. */

并且您应该将其用作指向 50 个字符数组 (char [50]) 的指针。