Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/c/71.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/android/195.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C 我应该使用strdup()还是只分配一个地址?_C - Fatal编程技术网

C 我应该使用strdup()还是只分配一个地址?

C 我应该使用strdup()还是只分配一个地址?,c,C,我有一个结构,其中一个成员是指向char的指针 假设一个结构看起来像 struct{ int a; char *cp; }X; 如果我应该这样做,我有点困惑 X.cp = str; 或 str是一个字符串 决定采用哪种实现的标准是什么?如果在使用X.cp之前可以销毁或重新使用原始字符串,请使用strdup 例如,如果str是函数中的本地数组,并且在X仍在使用时从函数返回,则需要复制字符串。或者如果str是动态分配的字符串,并且函数调用free(s

我有一个结构,其中一个成员是指向char的指针

假设一个结构看起来像

  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
did
strdup(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) );