我试图了解如何以最干净/最安全的方式解决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;
}
编译器的错误是:
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;
}
这按预期工作,但我想知道是否有更好的方法来做到这一点 . 谢谢 .
3 回答
第一个例子不起作用,因为你不能为数组赋值 - 在这方面,数组像const指针一样工作(排序) . 你可以做的是将一个新值复制到数组中:
如果您事先知道字符串的最大大小,则可以使用字符数组,例如,在第一个示例中,您100%确定该名称将适合19个字符(而不是20个,因为始终需要一个字符来存储终止零值) .
相反,如果您不知道字符串可能的最大大小,并且/或者您希望优化内存使用情况,指针会更好 . 避免为名称“John”保留512个字符 . 但是,使用指针,您需要动态分配它们指向的缓冲区,并在不再需要时释放它,以避免内存泄漏 .
Update: 动态分配缓冲区的示例(使用第二个示例中的struct定义):
将字符串视为抽象对象,将char数组视为容器 . 字符串可以是任何大小,但容器必须至少比字符串长度多1(以容纳空终止符) .
C对字符串的语法支持非常少 . 没有字符串运算符(只有char-array和char-pointer运算符) . 您无法分配字符串 .
但是你可以调用函数来帮助实现你想要的 .
这里可以使用
strncpy()
函数 . 为了最大限度地保证安全,我建议遵循以另请查看
strncat()
和memcpy()
函数 .这两种结构是不同的 . 初始化第一个结构时,分配大约40个字节的内存 . 初始化第二个结构时,分配大约10个字节的内存 . (实际金额取决于架构)
您可以使用字符串文字(字符串常量)来初始化字符数组 . 这就是为什么
适用于第一个例子 .
您不能在C中指定(在传统意义上)字符串 .
当您的代码执行时,您拥有的字符串文字(“John”)将被加载到内存中 . 使用其中一个文字初始化数组时,该字符串将复制到新的内存位置 . 在第二个示例中,您只是将指针复制到字符串文字的(位置) . 做类似的事情:
可能导致编译或运行时错误(我不确定 . )这是一个坏主意,因为你正在修改文字字符串“Hello”,例如在微控制器上,它可能位于只读存储器中 .