Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/c/72.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
字符串与字符串文字:直接赋值还是strcpy/strncpy?_C_Struct_Strcpy - Fatal编程技术网

字符串与字符串文字:直接赋值还是strcpy/strncpy?

字符串与字符串文字:直接赋值还是strcpy/strncpy?,c,struct,strcpy,C,Struct,Strcpy,我想我在理解字符串和字符串文字时遇到了一些问题 这是我从我的类中学到的,当传递给函数时,const char*表示这是字符串文字,而char*表示字符串 假设我有一个结构声明: struct node{ char *name; struct node *next; }; 还有一个函数,这是我想要实现的函数: void load_buffer(struct node *input_node, char *input_name); 此函数用于将输入_名称分配给结构的成员名称 我的

我想我在理解字符串和字符串文字时遇到了一些问题

这是我从我的类中学到的,当传递给函数时,const char*表示这是字符串文字,而char*表示字符串

假设我有一个结构声明:

struct node{
    char *name;
    struct node *next;
};
还有一个函数,这是我想要实现的函数:

void load_buffer(struct node *input_node, char *input_name);
此函数用于将输入_名称分配给结构的成员名称

我的困惑来自这里。在load_buffer的主体中,我是否应该写入:

input_node->name = input_name;
或者我应该使用strcpy/strncpy来做这个

strcpy(input_node->name, input_name);// Suppose it's safe in this case.
总之,我不确定是否应该使用直接赋值或strcpy族函数将字符串/字符串文本赋值给结构的成员


谢谢你的帮助。:)

在指针分配的情况下,每个节点中的指针将指向相同的位置。因此,节点将始终指向更新的值。如果要使每个节点包含不同的
输入
,则此方法不适合您的要求

input_node->name = input_name;
如果是strcpy,每个节点中的指针将指向不同的位置。在此之前,您需要为每个指针创建内存

input_node->name = malloc(strlen(input_name)+1); //Allocate memory first.
strcpy(input_node->name, input_name);// Suppose it's safe in this case.
可视化:

。。。传递给函数时,
const char*
表示这是字符串文字,而
char*
表示字符串

不完全是
const char*
声明函数不会尝试修改字符串。因此,它非常适合字符串Literal,因为它们无法修改

对于你的问题,答案是它取决于你的实际需求。但是,如果结构可以在函数之后保持,并且字符串可以在调用者中更改,则只需存储传递的指针。让我们看看下面的代码:

void load_buffer(struct node *input_node, const char *input_name) {
    input_node->name = name;
}

struct node nodes[2];
char buf[4];
const char *data[] = { "foo", "bar"};
for (int i=0; i<2; i++) {
    strcpy(buf, data[i]);    // suppose it is read from somewhere (file, stdin, socket)
    load_buffer(node + i, buf);
}

但是当节点不再使用时,您应该释放
名称
成员…

首先解决一些术语:

  • 这是字符串文字:
    “我是字符串文字”
  • 这是一种类型:
    char*
    (也称为指向char的指针)
  • 这也是一种类型:
    常量字符*
    (也称为指向常量字符的指针)
  • 这是类型为
    char*
    char*str
  • 这是类型为
    const char*
    const char*cstr
指针不是字符串文字。指针可以指向字符串文字、数组,也可以指向单个元素,也可以为null

C
中,字符串是以null结尾的字符数组

C
中,可以将
char*
变量指定给字符串文字,但修改字符串文字是非法的,因此强烈建议不要这样做。允许这样做的原因是历史的

char* a = "asd"; // allowed, but frowned upon
// a points to a string literal, so we can say a is a string
// a is not a string literal

char b = 'x';
char* c = &b;
// c points to a single char
// we cannot say c is a string

char d[10] = "asd";
// d is a char array. Its content is a string, so we can say d is a string.
// d is not a string literal
// the string literal is copied into the array d

char* e = d; // or equivalent char* e = &d[0];
// e points to a string

char f[4] = {'a', 's', 'd', '\0'};
// f is an array. Its content is a string, so we can say f is a string

char* g = f;
// g points to a string. We can say g is a string

char h[3] = {'a', 's', 'd'};
// h is an array. Its content is NOT a string, because the char array is not null terminated

char* i = h;
// i is not a string
现在再次检查上述内容,但不要将
char
替换为
const char
,所有注释仍然有效(除了`const char*a=“asd”现在可以了)


现在来谈谈手头的问题

有两种情况:

  • 每个节点都有自己的字符串,并且“拥有”该字符串。每个节点负责为字符串分配内存并释放该内存。字符串的寿命与节点的寿命相同。在这种情况下,使用
    malloc
    strcpy
    为每个节点创建一个字符串。当节点被销毁时,不要忘记释放字符串。这是最常见的场景,可能是您想要的

  • 节点不拥有自己的字符串,而是指向外部字符串。不允许为该字符串分配或释放内存。还有另一个实体负责管理该字符串的生存期,并确保该字符串至少在节点处于活动状态时处于活动状态。字符串可以在没有内存泄漏的情况下超过节点

  • 例如,考虑这种情况:

    • 有一个字符串资源列表。此列表拥有这些资源。此列表将使用场景1
    • 我们需要保留两个不同的R排序顺序。因此我们有两个列表A和B,它们将使用场景2:A和B中的每个节点都指向一个R字符串

    输入节点->名称=输入名称输入\u名称
    以后不会更改,code>应该可以。这取决于您想要的语义:
    结构
    是否必须拥有引用的字符串,以及如何分配它?如果您有指针,则需要在使用
    strcpy
    之前将其指向有效的位置。至于使用哪一种,这要看情况而定。您是否总是使用字符串文字?您需要修改字符串吗?附加到它们?不,我不需要修改字符串,我将使用的“字符串”是从文件中读取的,那么这是否表明我应该使用直接赋值而不是strcpy族函数?所有节点的“字符串”都是相同的?如果是
    malloc()
    ,则必须
    free()
    char* a = "asd"; // allowed, but frowned upon
    // a points to a string literal, so we can say a is a string
    // a is not a string literal
    
    char b = 'x';
    char* c = &b;
    // c points to a single char
    // we cannot say c is a string
    
    char d[10] = "asd";
    // d is a char array. Its content is a string, so we can say d is a string.
    // d is not a string literal
    // the string literal is copied into the array d
    
    char* e = d; // or equivalent char* e = &d[0];
    // e points to a string
    
    char f[4] = {'a', 's', 'd', '\0'};
    // f is an array. Its content is a string, so we can say f is a string
    
    char* g = f;
    // g points to a string. We can say g is a string
    
    char h[3] = {'a', 's', 'd'};
    // h is an array. Its content is NOT a string, because the char array is not null terminated
    
    char* i = h;
    // i is not a string