我有这段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我对两种情况下记忆中发生的事情感兴趣.
这取决于你以后想做什么birth.month.如果您无意更改它,那么第一个更好(更快,不需要内存清理要求,并且每个Date_t对象共享相同的数据).但如果是这种情况,我会改变monthto 的定义const char *.实际上,任何写入的尝试*birth.month都会导致未定义的行为.
第二种方法会导致内存泄漏,除非你记得free(birth.month)在birth超出范围之前.
你是对的,第二种变体是"好的".
这是区别:
使用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->month来const char*对清晰度和正确性.