2010-06-28 46 views
37

我想了解如何在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: In function ‘main’: main.c:18: error: incompatible types when assigning to type ‘char[20]’ from type ‘char *’

据我所知,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; 
} 

可正常工作,但我不知道是否有这样做更好的方法。谢谢。

+0

如果我们在'main()'中声明结构体,那么只有人可以在里面访问它。 尝试从主要移出使用它作为全球 – EsmaeelE 2018-03-03 19:58:27

回答

29

第一个示例不起作用,因为您无法将值分配给数组 - 数组在这方面像const指针一样工作(有点)。什么可以做,虽然是复制一个新的值到数组:

strcpy(p.name, "Jane"); 

字符数组都很好,如果你知道该字符串的最大大小提前使用,例如在第一个示例中,您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); 
7

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

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

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

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

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

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

+1

现在最好的答案,但也是佩特的一个很好(显示如何使用指针),所以我等一会儿,看看更多的人可以添加更多的提示/关于这个问题的建议。 – 2010-06-28 10:38:07

4

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

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

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

在第一个例子中工作。

您不能分配(传统意义上的)的字符串在C

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

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

可能会导致编译或运行时错误(我不知道)。这是一个坏主意,因为要修改的文本字符串“你好”的,例如在单片机,可设在只读存储器中。

+0

你是对的,你写的任务会导致段错误,因为你正试图改变一个指针的值,但是引用我的例子就像char * string =“Hello”; string =“C”; (注意最后一条语句没有指针分配),它按预期工作。 – 2010-06-28 10:07:34

+1

我想提一下,“改变指针值”并不一定会导致段错误。原始帖子中的代码段导致段错误的原因是因为您试图修改位于受限地址空间中的内存。 – Gus 2010-06-28 10:13:53

相关问题