Вы правы, второй вариант - "хороший".
Вот разница:
С 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*
для ясности и правильности.