如何正确分配一个新的字符串值?

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

#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; } 

编译器的错误是:

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

我明白,C(而不是C ++)没有字符串类型,而是使用字符数组,所以另一种方法是改变示例结构来保存字符指针:

 #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; } 

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

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

 strcpy(p.name, "Jane"); 

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

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

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

 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); 

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

C对字符串的语法支持很少。 没有字符串操作符(只有char-array和char-pointer操作符)。 你不能分配字符串。

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

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

 strncpy(p.name, "Jane", 19); p.name[19] = '\0'; //add null terminator just in case 

也可以看看strncat()memcpy()函数。

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

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

人p = {“John”,“Doe”,30};

在第一个例子中工作。

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

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

 char* string = "Hello"; *string = 'C' 

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