C语言 如何正确分配新的字符串值?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/3131319/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-02 05:44:56  来源:igfitidea点击:

How to correctly assign a new string value?

cstringstructstrcpy

提问by Gianluca Bargelli

I'm trying to understand how to solve this trivial problem in C, in the cleanest/safest way. Here's my example:

我试图了解如何以最干净/最安全的方式在 C 中解决这个微不足道的问题。这是我的例子:

#include <stdio.h>

int main(int argc, char *argv[])
{
    typedef struct
    {
        char name[20];
        char surname[20];
        int unsigned age;
    } person;

    //Here i can pass strings as values...how does it works?
    person p = {"John", "Doe",30};

    printf("Name: %s; Age: %d\n",p.name,p.age);
    // This works as expected...
    p.age = 25;
    //...but the same approach doesn't work with a string
    p.name = "Jane";

    printf("Name: %s; Age: %d\n",p.name,p.age);

    return 1;
}

The compiler's error is:

编译器的错误是:

main.c: In function ‘main': main.c:18: error: incompatible types when assigning to type ‘char[20]' from type ‘char *'

main.c:在函数“main”中:main.c:18:错误:从类型“char *”分配给类型“char[20]”时类型不兼容

I understand that C (not C++) has no String type and instead uses arrays of chars, so another way to do this was to alter the example struct to hold pointers of chars:

我知道 C(不是 C++)没有 String 类型,而是使用字符数组,因此另一种方法是更改​​示例结构以保存字符指针:

#include <stdio.h>

int main(int argc, char *argv[])
{
    typedef struct
    {
        char *name;
        char *surname;
        int unsigned age;
    } person;

    person p = {"John", "Doe",30};

    printf("Name: %s; Age: %d\n",p.name,p.age);

    p.age = 25;

    p.name = "Jane";

    printf("Name: %s; Age: %d\n",p.name,p.age);

    return 1;
}

This works as expected but I wonder if there a better way to do this. Thanks.

这按预期工作,但我想知道是否有更好的方法来做到这一点。谢谢。

采纳答案by Péter T?r?k

The first example doesn't work because you can't assign values to arrays - arrays work (sort of) like const pointers in this respect. What you can do though is copy a new value into the array:

第一个例子不起作用,因为你不能给数组赋值——在这方面,数组的工作(有点)像 const 指针。您可以做的是将新值复制到数组中:

strcpy(p.name, "Jane");

Char arrays are fine to use if you know the maximum size of the string in advance, e.g. in the first example you are 100% sure that the name will fit into 19 characters (not 20 because one character is always needed to store the terminating zero value).

如果您事先知道字符串的最大大小,则可以使用字符数组,例如,在第一个示例中,您 100% 确定名称将适合 19 个字符(不是 20 个,因为总是需要一个字符来存储终止零价值)。

Conversely, pointers are better if you don't know the possible maximum size of your string, and/or you want to optimize your memory usage, e.g. avoid reserving 512 characters for the name "John". However, with pointers you need to dynamically allocate the buffer they point to, and free it when not needed anymore, to avoid memory leaks.

相反,如果您不知道字符串可能的最大大小,和/或您想优化内存使用,例如避免为名称“John”保留 512 个字符,则指针会更好。但是,对于指针,您需要动态分配它们指向的缓冲区,并在不再需要时释放它,以避免内存泄漏。

Update:example of dynamically allocated buffers (using the struct definition in your 2nd example):

更新:动态分配缓冲区的示例(使用第二个示例中的结构定义):

char* firstName = "Johnnie";
char* surname = "B. Goode";
person p;

p.name = malloc(strlen(firstName) + 1);
p.surname = malloc(strlen(surname) + 1);

p.age = 25;
strcpy(p.name, firstName);
strcpy(p.surname, surname);

printf("Name: %s; Age: %d\n",p.name,p.age);

free(p.surname);
free(p.name);

回答by Artelius

Think of strings as abstract objects, and char arrays as containers. The string can be any size but the container must be at least 1 more than the string length (to hold the null terminator).

将字符串视为抽象对象,将字符数组视为容器。字符串可以是任意大小,但容器必须至少比字符串长度多 1(以容纳空终止符)。

C has very little syntactical support for strings. There are no string operators (only char-array and char-pointer operators). You can't assign strings.

C 对字符串的语法支持很少。没有字符串运算符(只有字符数组和字符指针运算符)。您不能分配字符串。

But you can call functions to help achieve what you want.

但是你可以调用函数来帮助实现你想要的。

The strncpy()function could be used here. For maximum safety I suggest following this pattern:

strncpy()函数可以在这里使用。为了最大程度的安全,我建议遵循以下模式:

strncpy(p.name, "Jane", 19);
p.name[19] = '
char* string = "Hello";
*string = 'C'
'; //add null terminator just in case

Also have a look at the strncat()and memcpy()functions.

也看看strncat()memcpy()功能。

回答by Gus

The two structs are different. When you initialize the first struct, about 40 bytes of memory are allocated. When you initialize the second struct, about 10 bytesof memory are allocated. (Actual amount is architecture dependent)

这两个结构是不同的。初始化第一个结构体时,会分配大约 40 字节的内存。初始化第二个结构时,将分配大约 10 个字节的内存。(实际数量取决于架构)

You can use the string literals (string constants) to initalize character arrays. This is why

您可以使用字符串文字(字符串常量)来初始化字符数组。这就是为什么

person p = {"John", "Doe",30};

人 p = {"John", "Doe",30};

works in the first example.

在第一个示例中工作。

You cannot assign (in the conventional sense) a string in C.

你不能在 C 中分配(在传统意义上)一个字符串。

The string literals you have ("John") are loaded into memory when your code executes. When you initialize an array with one of these literals, then the string is copied into a new memory location. In your second example, you are merely copying the pointer to (location of) the string literal. Doing something like:

当您的代码执行时,您拥有的字符串文字(“John”)将加载到内存中。当您使用这些文字之一初始化数组时,该字符串将被复制到新的内存位置。在您的第二个示例中,您只是将指针复制到字符串文字(的位置)。做类似的事情:

##代码##

might cause compile or runtime errors (I am not sure.) It is a bad idea because you are modifying the literal string "Hello" which, for example on a microcontroler, could be located in read-only memory.

可能会导致编译或运行时错误(我不确定。)这是一个坏主意,因为您正在修改文字字符串“Hello”,例如在微控制器上,它可能位于只读存储器中。