Почему массив символов нужен strcpy, а char – нет – используя структуры в C

У меня есть недоразумение относительно этого кода –

typedef struct _EXP{ int x; char* name; char lastName[40]; }XMP ...main... XMP a; a.name = "eaaa"; a.lastName = strcpy(a.lastName, "bbb"); 

Почему я не могу использовать: a.lastName = "bbbb"; и это все?

Хорошо рассмотрим типы здесь. Массив имеет содержимое строки, а char* просто указывает на данные. Следовательно, для массива требуются strcpy и друзья.

Кроме того, если вы выделили память для char* в куче или стеке, а затем захотеть присвоить ей некоторый контент, вам также придется использовать strcpy потому что простое назначение создало бы висячий указатель (т. Е. Утечку памяти).

Поскольку местоположение массива фиксировано, а значение указателя (которое само по себе является местоположением) не является. Вы можете назначить новые значения указателю, но не массиву.

Под капотом они оба одинаковы; имя массива в C является указателем, но с точки зрения семантики вы не можете переназначить массив, но вы можете переместить указатель.

Когда вы пишете

 a.name = "eaaa" ; 

компилятор будет выделять память для NULL завершенной строки eaaa\0 и, из-за этой инструкции, она заставит name указателя указывать на это местоположение (например, переменная name будет содержать адрес ячейки памяти, где первый байт строки проживает).

Если у вас есть массив, у вас уже есть выделенная область памяти (которая не может быть назначена другой ячейке памяти!), И вы можете заполнить ее только данными (в этом случае байтами, представляющими вашу строку).

Это мое понимание того, что может быть причиной этого.

Я думаю, что речь идет о том, как работает язык. C (а также C ++) создает неуправляемый код, что означает, что им не нужна среда (например, JVM) для управления памятью, streamовой передачи и т. Д. Таким образом, код создается для исполняемого файла, который запускается ОС напрямую , По этой причине исполняемый файл включает в себя информацию, например, сколько места, которое должно быть выделено для каждого типа (но не обязательно для динамических типов), включая массивы. (Именно поэтому C ++ представил файлы заголовков, поскольку это был единственный способ узнать размер объекта во время компиляции)

Таким образом, когда компилятор видит массив символов, он вычисляет, сколько места требуется для него на этапе компиляции и помещает эту информацию в исполняемый файл. При запуске программы stream может определить, сколько места требуется и выделяет большую часть памяти. Если вы измените это несколько раз, скажем, в функции C, каждое присваивание сделает предыдущие (ы) недействительными. Итак, IMO, поэтому компилятор этого не допускает.