C 我应该使用strdup()还是只分配一个地址?
我有一个结构,其中一个成员是指向char的指针 假设一个结构看起来像C 我应该使用strdup()还是只分配一个地址?,c,C,我有一个结构,其中一个成员是指向char的指针 假设一个结构看起来像 struct{ int a; char *cp; }X; 如果我应该这样做,我有点困惑 X.cp = str; 或 str是一个字符串 决定采用哪种实现的标准是什么?如果在使用X.cp之前可以销毁或重新使用原始字符串,请使用strdup 例如,如果str是函数中的本地数组,并且在X仍在使用时从函数返回,则需要复制字符串。或者如果str是动态分配的字符串,并且函数调用free(s
struct{
int a;
char *cp;
}X;
如果我应该这样做,我有点困惑
X.cp = str;
或
str是一个字符串
决定采用哪种实现的标准是什么?如果在使用
X.cp
之前可以销毁或重新使用原始字符串,请使用strdup
例如,如果str
是函数中的本地数组,并且在X
仍在使用时从函数返回,则需要复制字符串。或者如果str
是动态分配的字符串,并且函数调用free(str)代码>,您需要复制它
如果str
是您将每一行读入的缓冲区,则需要制作一个副本,因为您将覆盖它
如果对原始str
内容所做的更改应自动反映在X.cp
中,或者反之亦然,则您应该只分配指针。完美代码:
X.cp=malloc(strlen(str)+1);
if(X.cp==NULL)
{
printf("not enough memory \n");
return 0;
}
memset(X.cp,0,strlen(str)+1);
X.cp = strdup(str);
/**
*code
**/
if(X.cp)
free(x.cp);
让我们假设str
指向地址0x111111,并且从该地址开始的字符串是“foobar”
做X.cp=str后代码>,X.cp的值将为0x111111,即X.cp“点”到0x111111。此时printf(“%s”,X.cp)
和printf(“%s”,str)
都将打印foobar和printf(“%p”,X.cp)
和printf(“%p”,str)
都将打印0x111111。内存中唯一改变的是X.cp
(它只是0x111111,而不是字符串本身)的值
执行X.cp=strdup(str)后代码>,X.cp的值将不是0x111111,而是新分配的地址;让我们假设它是0x2222。
此外,存储在0x111111的字符串将被复制到从0x2222222开始的七个地址(即“f”o“o”b“a”r“\0”)。因此,在这种情况下,内存有两个变化:X.cp的值和新分配的包含字符串的地址块。在这种情况下,除printf(“%p”,X.cp)
外,上一种情况下的所有printf
将在此处产生相同的输出,它将打印0x22222
这两种分配给X.cp的方法有着截然不同的用途。如果希望在访问str时看到对X.cp的更改,则应使用第一种情况,反之亦然。另一方面,当您希望能够独立地更改X.cp和str时,应该使用第二种情况。注意第一种情况:如果您取消分配X.cp或str中的一个,那么您不能尝试取消引用另一个,否则您将获得SEGFULT
记住“字符串”是特殊的。它们不是C中的数据类型。它们是内存中以'\0'
字符
结尾的字符块。
这就是为什么您不应该执行类似于*(X.cp)=*str
(除非您真的只想复制一个字符)的操作
最后,我应该注意到,如果不使用strdup()
,则调用变量X.cp
,这可能是一个坏名字,因为strdup()是一个名为“cp”的副本。如果知道控制str
,则使用指针。比如,如果您在自己的函数中分配了str
,而不将其存储在其他任何地方,那么复制它就没有意义了
如果要与其他人共享对str
的更改,请使用指针
如果你想将自己与其他人使用的str
隔离开来,请执行strdup
有时您可以知道这一点,但通常您不知道,但使用struct的人确实知道。让用户决定。编写函数以获取char*
并使用该指针。记录您的函数将使用原始指针
X* X_new( char *str ) {
X* x = malloc( sizeof(X) );
x->cp = str;
x->a = 42; // I don't know what a is for
return x;
}
// The caller lets x control str, x->cp is str.
X* x = X_new( str );
// The caller passes in a copy of str, x->cp and str are independent of each other.
X* y = X_new( strdup(str) );
通过使用指针,它允许用户决定传入指针或副本。如果X_new
didstrdup(str)
用户将没有发言权。这取决于谁或什么将拥有cp
将指向的内存区域。X
会拥有它吗?还是别的?很简单。是否要引用原始str
或复制字符串?旁注:如果a
是内存的长度,我喜欢malloc
和memcpy
——知道长度应该可以减少strdup
所需的操作。只有你才能回答这个问题。如果str是一个全局变量呢?这取决于你如何使用它们,就像我说的。如果对其中一个的更改应该在另一个中看到,则应该指定指针。如果它们应该独立运行,则需要制作一个副本。@Nguaial如果它是全局的,并且需要指向该全局的指针,请存储该指针。如果您想避免对该全局文件进行更改,请复制它。也要考虑它是否应该是全局的。StrudUp()已经做了MalCube()和SrcPy*()。不需要执行malloc()和memset()。strlen()使用起来非常危险。如果str不是以NUL字符结尾怎么办?在编写代码后,您可以使用klocwork检查内存泄漏,您会发现这是正确的代码。试试klocwork,这是个好工具。PS:我忘记了malloc和strlen中的+1。这似乎并没有回答问题,问题是要复制字符串还是只存储指向现有字符串的指针。
X* X_new( char *str ) {
X* x = malloc( sizeof(X) );
x->cp = str;
x->a = 42; // I don't know what a is for
return x;
}
// The caller lets x control str, x->cp is str.
X* x = X_new( str );
// The caller passes in a copy of str, x->cp and str are independent of each other.
X* y = X_new( strdup(str) );