Эта ошибка относительно безопасна, так как приводит к сбою на этапе компиляции.
Однако, это совершенно неудобно.
Присваивание строк
Free(str6);
Проиллюстрирую создание строк на фрагментах кода с комментариями.
Создание строк
Строки и языке С
Строка в Си - это последовательность байт (букв, символов, литер, character), завершающаяся в конце специальным признаком - байтом '\0'. Этот признак добавляется компилятором автоматически, когда мы задаем строку в виде "строка". Длина строки (т.е. число литер, предшествующих '\0') нигде явно не хранится. Длина строки ограничена лишь размером массива, в котором сохранена строка, и может изменяться в процессе работы программы в пределах от 0 до длины массива-1. При передаче строки в качестве аргумента в функцию, функции не требуется знать длину строки, т.к. передается указатель на начало массива, а наличие ограничителя '\0' позволяет обнаружить конец строки при ее просмотре.
char str1[10]; // Строка - массив из 10 символов. Начальное значение символов не определено.
char str2[10]="Hello";
H
e
l
l
o
\0
/* Используется инициализация (не присваивание!). В первые 5 символов записывается “Hello”, в 6 – нуль-терминатор ‘\0’, значение трех последних не определено.*/
//Ошибка. Массив из 10 элементов нельзя инициировать более длинной последовательностью.
char str5[]="Very long line";
/*Компилятор автоматически определяет длину массива (в нашем случае 15) и инициализирует его последовательностью символов. ‘\0’ добавится автоматически*/
char* str6;
/*Строка - указатель на символ. В большинстве случаев для ее использования
потребуется выделить память.*/
str6=new char[10];
.
.
Первый и самый очевидный способ присваивания строк – присваивание отдельных символов. Например,
str1[0]=’H’;
str1[1]=’e’;
str1[2]=’l’;
str1[3]=’l’;
str1[4]=’o’;
str1[5]=’\0’;
Не зная о правильных способах, начинающие программисты часто «выдумывают» свои способы присваивания строк, конечно, неправильные. Вот несколько примеров:
char str1[10], str2[10];
str1="Hello";
str2=str1;
//Одна и та же ошибка в обоих операторах =.
//Имя массива нельзя использовать в левой части оператора присваивания.
char str1[10]= "Hello";
char* str2;
str2=str1;
str2[1]='u';
Этот код откомпилируется, но, возможно, содержит «идеологическую» ошибку. Неправильно полагать, что в str2 теперь содержится копия str1. На самом деле этот указатель указывает не на копию, а на ту же самую строку. При любом изменении содержимого str2 изменяется str1. Однако, если именно это и требуется, то все в порядке.
Еще один вариант присваивания указателей – присваивание их строковым литералам. Как вы помните, тип строкового литерала – const char*, а значит такой код работает:
const char* str;
str="Hello";
Опять же следует помнить, что str указывает на строковый литерал, а не на его копию. Но, к сожалению, такой код тоже сработает:
char* str; // Нет const
str="Hello";
Здесь мы имеем дело с наследством C, в котором отсутствовал const. Поэтому стандарт С++ разрешает такое присваивание.