====== строки ====== В Си для представления строк используются массивы символов. Каждая строка в качестве завершающего символа содержит символ ''\0'' т.н. нулевой символ / нулевой байт. char message[] = "Hello"; size_t length = sizeof(message)/sizeof(char); // 6 символов for(size_t i=0; i Если бы мы определяли массив message не как строку, а именно как массив символов, то последним элементом должен был бы идти нулевой символ: char message[] = {'H', 'e', 'l', 'l', 'o', '\0'}; ===== Явное определение длинны ===== // a b c \0 - все верно char abc[4] = "abc"; // нулевой байт будет отброшен char abc[3] = "abc"; // лишнее место заполниться нулевыми байтами char abc[5] = "abc"; // поведение определено компилятором // например gcc отбросит лишние символы char abc[2] = "abc"; ===== Строка как указатель ===== Но в языке Си также для представления строк можно использовать [[pointers|указатели]] на тип char: #include int main(void) { char *hello = "Hello METANIT.COM!"; printf("%s", hello); return 0; } Заданные таким образом строки __изменять нельзя__, в том числе указателями. В языке Си для работы со строками применяется такой механизм как //string interning// или //интернирование строк//. В этом случае строки в виде строковых литералов сохраняются в приложении в секции ''.rodata'' (read-only data), которые предназначены для данных только для чтения, а строковые литералы рассматриваются как неизменяемые данные. Указатель на строковой литерал содержит адрес первого бита литерала в этой секции неизменяемых данных Если два указателя с разными идентификаторами будут ссылаться на одинаковые строковые литералы - они будут ссылаться на один и тот же адрес в памяти. Как и любому указателю, такой строке можно задать значение NULL, но это будет не то же самое, что ''%%""%%'' тк такая строка не будет содержать нулевого байта.