我有以下数据类型:
typedef struct {
int num;
char *str;
} NumStr;
和变量x:
NumStr *x;
如何为str指针分配堆空间?我试着
x->str = (char*)malloc(sizeof(char*));
但是它不工作。
我对C很陌生,所以如果我错过了一些明显的东西,我很抱歉。提前谢谢。
像NumStr*
这样的指针指向内存中的某个地方-因此您需要在分配x->str
之前分配x
:
NumStr* x = malloc(sizeof(*x));
.
请注意,没有必要像您所做的那样强制转换为(char*)
-并且不要忘记按特定顺序强制转换为free(x->str);
和free(x);
。
至于你的实际问题:
我如何为str指针分配堆空间?
你所做的(x->str = (char*)malloc(sizeof(char*));
)可能不是你想要的。根据您的系统,sizeof(char*)
很可能是4或8,但更重要的是,它与x->str
指向的char
对象无关。在分配动态内存时,一般范例是为"上一级"类型分配空间。从您分配给的左值,作为sizeof
类型和所需空间量的组合。也就是说,对于某些类型T
,您希望以以下方式分配空间:
// 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);
这样做的原因是更少的维护。假设T
是char
,过了一段时间,它变成了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
对象分配空间。
// 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
分配空间是愚蠢的,正如您的变量名所表明的,这意味着是一个字符串,因此您将需要多个char
s:
x->str = malloc(sizeof(char) * numOfCharsIWant);
此外,C标准将sizeof(char)
定义为1,因此也可以省略:
x->str = malloc(numOfCharsIWant);
最后,你应该只动态分配内存,如果你有To,在实践中通常可以归结为:
- 你不知道你需要多少内存,直到运行
- 你需要"很多"的内存。什么"很多"?方法取决于您的系统,但根据我的经验,桌面linux上每个执行线程的默认堆栈大小是8MB,这对于通常的操作来说是足够的空间。
如果你知道你的最大字符串大小是多少,你可以绕过动态内存分配,像下面这样做:
#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: %sn", x.num, x.str);
// no need to clean up dynamically allocated memory, since there is none
return 0;
}
你可以直接做
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初始化(如Daniel的回答),然后才初始化分配的内存。
(和使用-allocs时一样)您需要稍后自己对它所指向的内存进行free
。
再澄清一件事:x->str = (char*)malloc(sizeof(char*));
应该更正为x->str = malloc(sizeof(char));
,可选x->str = malloc(5*sizeof(char))
或其他。
你使用了
x->str = (char*)malloc(sizeof(char*));
,但是sizeof
操作符会给你指针类型本身的大小(这不是你想要的,因为指针已经在结构体中分配了空间)。如果你想为一个字符串分配空间,比如说,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]
)的指针来使用。