С точки зрения C, наиболее существенным отличием между c3
и остальными является то, что вам не разрешается пытаться изменить базовые символы с помощью c3
. Мне часто бывает полезно думать об этом так:
char *xyz = "xyz";
создаст модифицируемый указатель в стеке и сделает его указателем на неизменяемую последовательность символов {'x','y','z','\0'}
. С другой стороны,
char xyz[] = "xyz";
создаст модифицируемый массив в стеке, достаточно большом для размещения последовательности символов {'x','y','z','\0'}
, а затем скопирует в него эту последовательность символов. Содержимое массива будет изменяемым. Имейте в виду, что в стандарте ничего не говорится о стеках, но обычно так и делается. В конце концов, это просто память.
Формально c3
- это указатель на строковый литерал, тогда как c1
и c2
- это массивы символов, которые заканчиваются нулевым символом. Когда они передаются в функции, такие как printf
, они распадаются на указатель на первый элемент массива, что означает, что они будут обрабатываться идентично c3
в этой функции (на самом деле они распадаются при довольно многих обстоятельствах, см. третья цитата из c99 ниже для исключений).
Соответствующие разделы C99: 6.4.5 String literals
, что объясняет, почему вам не разрешено изменять то, на что c3
указывает:
Не определено, различаются ли эти массивы при условии, что их элементы имеют соответствующие значения. Если программа пытается изменить такой массив, поведение не определено.
и почему он имеет нулевой терминатор:
На этапе перевода 7 байт или код нулевого значения добавляются к каждой многобайтовой последовательности символов, полученной из строкового литерала или литералов.
И 6.3.2.1 Lvalues, arrays, and function designators
при 6.3 Conversions
состояниях:
За исключением случаев, когда это операнд оператора sizeof или унарный оператор &, или строковый литерал, используемый для инициализации массива, выражение с типом '' массив типа '' преобразуется в выражение с типом ' указатель на тип, который указывает на начальный элемент объекта массива и не является lvalue. Если объект массива имеет класс хранения регистров, поведение не определено.