Для ясности, нет ничего "сломанного" в strcpy()
;если у него «вызвало некоторые проблемы в прошлом» для вас, то есть из-за ошибок в вашем использовании, а не из-за внутренней проблемы с strcpy()
, и вам, возможно, следует опубликовать вопрос об этом, такВаши неправильные представления могут быть исправлены.
Семантика между назначением указателя строки и копированием строки различается, поэтому это зависит от того, что вы пытаетесь сделать.
x
это массив указателей.Назначение:
x[0] = q[0];
Копирует ли не строку, указанную q[0]
, в память, указанную x[0]
.скорее это изменяет значение x[0]
на адрес строки, на которую ссылается q[0]
.Таким образом, они оба ссылаются на одну и ту же строку в памяти.Строковые данные перемещены или скопированы , в данном случае только ссылка на строковые литералы:
q[0] --> "Hello"
^
|
x[0] -----
В этом смысле x
не "новый массив строк" , как вы описываете, но массив указателей на одинаковых строк .Возможно, это не семантическое поведение, которое вы намеревались.
Если вы попытаетесь:
strcpy( x[0], q[0] ) ;
Это будет семантическая ошибка, поскольку в ваших фрагментах x[0]
не указывает на какую-либо определенную память, поэтому строковые данные, на которые ссылается q[0]
будет скопировано в какое-то неопределенное место с неопределенными результатами - ничего хорошего, даже если на первый взгляд будет работать .
Если x[0]
ссылается на некоторые из них правильновыделенное пространство, например, либо объявленным как массив таким образом:
char x[2][128] ;
, либо выделенным динамически:
x[0] = malloc( 128 ) ;
, либо первым назначенным в другое допустимое пространство:
char a[120]
x[0] = a ;
Или путем динамического выделения a
, как в примере в вашем вопросе.
Тогда strcpy( x[0], q[0] )
является допустимой операцией и скопирует строку, на которую ссылается q[0]
в пространство, указанное x[0]
:
q[0] --> "Hello"
x[0] --> "Hello"
Критически в этом случае строки не ссылаются на одно и то же пространство в памяти.
Обратите внимание, что если вы действительно хотели присваивание указателя строки semantics (что, вероятно, менее вероятно), а q
относится к константам литеральных строк , тогда для более безопасного кода важно объявить массивы как указатели на const
data:
const char* q[2] ;
const char* x[2] ;
Массив q
должен быть объявлен const
в этом случае в любом случае, но ясно, что x
не должен быть константой, если вы хотите семантику string-copy .
Полезно, объявив его const
, любая попытка strcpy()
завершится неудачей детерминистически при компиляции, а не неопределенным, ошибочным и, возможно, скрытым поведением во время выполнения.Таким образом, он применяет предполагаемую семантику, если это действительно то, что вы хотели.Точно так же это останавливает вас от попытки изменить данные, на которые ссылается q[n]
, что также будет неопределенным поведением (но, как правило, приведет к ошибке времени выполнения в современной настольной ОС).