以下哪个选项是将字符串值赋值给C中的变量的好方法?

roo*_*kie 5 c

我有这段C代码:

#include<stdio.h>
#include<stdlib.h>
#include<string.h>

typedef struct Date {
    int date;
    char* month;
    int year;

} Date_t;

typedef Date_t* pDate_t;

void assignMonth(pDate_t birth)
{
    //1)
    birth->month = "Nov";

    //2)
    //birth->month = malloc(sizeof(char) * 4);
    //birth->month = strcpy(birth->month, "Nov");

}

int main()
{
    Date_t birth;
    birth.date = 13;
    assignMonth(&birth);
    birth.year = 1969;


    printf("%d %s %d\n",birth.date, birth.month, birth.year);
    return 0;
}
Run Code Online (Sandbox Code Playgroud)

在函数中,assignMonth我有两种分配月份的可能性.两者都在输出中给出了相同的结果,那么它们之间的区别是什么?我认为第二种变体是好的,我错了吗?如果是,为什么?如果没有,为什么?

在此先感谢您的帮助.

PS我对两种情况下记忆中发生的事情感兴趣.

Oli*_*rth 9

这取决于你以后想做什么birth.month.如果您无意更改它,那么第一个更好(更快,不需要内存清理要求,并且每个Date_t对象共享相同的数据).但如果是这种情况,我会改变monthto 的定义const char *.实际上,任何写入的尝试*birth.month都会导致未定义的行为.

第二种方法会导致内存泄漏,除非你记得free(birth.month)birth超出范围之前.


Tyl*_*nry 6

你是对的,第二种变体是"好的".

这是区别:

使用1,birth->month最终指向字符串文字"Nov".birth->month在这种情况下尝试修改内容是错误的,因此birth->month应该真的是一个const char*(许多现代编译器会因此而对作业进行警告).

使用2,birth->month最终指向已分配的内存块,其内容为"Nov".然后您可以自由修改内容birth->month,类型char*是准确的.需要注意的是,您现在还需要free(birth->month)在完成此操作后释放此内存.

2是一般的正确方法的原因,即使在这种情况下1似乎更简单,1通常是误导.在C中,没有字符串类型(只是字符序列),因此没有在字符串上定义赋值操作.对于双char*S,s1并且s2,s1 = s2不改变字符串值指向s1是一样的s2,它使s1点在完全相同的字符串作为s2.这意味着任何改变s1都会影响内容s2,反之亦然.此外,您现在需要在释放该字符串时要小心,因为它free(s1); free(s2);会双重释放并导致错误.

也就是说,如果在你的程序birth->month将永远只能是几个常量字符串(之一"Jan","Feb"等等)变体1是可以接受的,但是你应该改变的类型birth->monthconst char*对清晰度和正确性.