I have this snippet of C code:
#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;
}
In the function assignMonth I have two possibilities for assigning month. Both give me the same result in the output, so what is the difference between them? I think that the second variant is the good one, am I wrong? If yes, why? If not, why?
Thanks in advance for any help.
P.S. I’m interested in what is going on in memory in both cases.
You’re correct, the second variant is the “good” one.
Here’s the difference:
With 1,
birth->monthends up pointing to the string literal"Nov". It is an error to try to modify the contents ofbirth->monthin this case, and sobirth->monthshould really be aconst char*(many modern compilers will warn about the assignment for this reason).With 2,
birth->monthends up pointing to an allocated block of memory whose contents are “Nov”. You are then free to modify the contents ofbirth->month, and the typechar*is accurate. The caveat is that you are also now required tofree(birth->month)in order to release this memory when you are done with it.The reason that 2 is the correct way to do it in general, even though 1 seems simpler in this case, is that 1 in general is misleading. In C, there is no string type (just sequences of characters), and so there is no assignment operation defined on strings. For two
char*s,s1ands2,s1 = s2does not change the string value pointed to bys1to be the same ass2, it makess1point at exactly the same string ass2. This means that any change tos1will affect the contents ofs2, and vice-versa. Also, you now need to be careful when deallocating that string, sincefree(s1); free(s2);will double-free and cause an error.That said, if in your program
birth->monthwill only ever be one of several constant strings ("Jan","Feb", etc.) variant 1 is acceptable, however you should change the type ofbirth->monthtoconst char*for clarity and correctness.