Почему этот код создает проблемы во время выполнения:
char stuff[100];
strcat(stuff,"hi ");
strcat(stuff,"there");
но это не так?
char stuff[100];
strcpy(stuff,"hi ");
strcat(stuff,"there");
Почему этот код создает проблемы во время выполнения:
char stuff[100];
strcat(stuff,"hi ");
strcat(stuff,"there");
но это не так?
char stuff[100];
strcpy(stuff,"hi ");
strcat(stuff,"there");
strcat
будет искать нуль-терминатор, интерпретировать это как конец строки и добавить туда новый текст, перезаписывая нулевой ограничитель в процессе и записывая новый нуль-терминатор в конце конкатенация.
char stuff[100]; // 'stuff' is uninitialized
Где нулевой ограничитель? stuff
не инициализирован, поэтому он может начинаться с NUL, или он может не иметь NUL в любом месте.
В С++ вы можете сделать это:
char stuff[100] = {}; // 'stuff' is initialized to all zeroes
Теперь вы можете сделать strcat, потому что первый символ "stuff" является нулевым терминатором, поэтому он будет добавляться в нужное место.
В C вам все равно нужно инициализировать "материал", что можно сделать несколькими способами:
char stuff[100]; // not initialized
stuff[0] = '\0'; // first character is now the null terminator,
// so 'stuff' is effectively ""
strcpy(stuff, "hi "); // this initializes 'stuff' if it not already.
В первом случае stuff
содержит мусор. strcat
требует, чтобы и пункт назначения, и источник содержали соответствующие строки с нулевым завершением.
strcat(stuff, "hi ");
сканирует stuff
для завершающего символа '\0'
, где он начнет копирование "hi "
. Если он не найдет его, он сработает с конца массива, и могут произойти сколь угодно плохие вещи (т.е. Поведение undefined).
Один из способов избежать проблемы:
char stuff[100];
stuff[0] = '\0'; /* ensures stuff contains a valid string */
strcat(stuff, "hi ");
strcat(stuff, "there");
Или вы можете инициализировать stuff
пустой строкой:
char stuff[100] = "";
который заполнит все 100 байтов stuff
нулями (повышенная ясность, вероятно, стоит какой-то незначительной проблемы с производительностью).
Потому что stuff
не инициализируется перед вызовом strcpy
. После объявления stuff
не является пустой строкой, это неинициализированные данные.
strcat
добавляет данные в конец строки - то есть находит нулевой ограничитель в строке и после этого добавляет символы. Неинициализированная строка не поддерживает нулевой ограничитель, поэтому strcat
может сбой.
Если вам нужно было выполнить инициализацию stuff
, как показано ниже, вы можете выполнить команду strcat:
char stuff[100] = "";
strcat(stuff,"hi ");
strcat(stuff,"there");
Кроме того, я бы посоветовал использовать strcpy
или strcat
, поскольку они могут привести к некоторым непредвиденным проблемам.
Используйте strncpy
и strncat
, поскольку они предотвращают переполнение буфера.
Strcat добавляет строку в существующую строку. Если строковый массив пуст, он не будет набирать конец строки ('\0'
), и это вызовет ошибку времени выполнения.
В соответствии с man-страницей Linux простой strcat реализован следующим образом:
char*
strncat(char *dest, const char *src, size_t n)
{
size_t dest_len = strlen(dest);
size_t i;
for (i = 0 ; i < n && src[i] != '\0' ; i++)
dest[dest_len + i] = src[i];
dest[dest_len + i] = '\0';
return dest;
}
Как вы можете видеть в этой реализации, strlen(dest)
не вернет правильную длину строки, если только dest
не инициализируется, чтобы исправить значения строки c. Вам может повезти иметь массив с первым значением нуля в char stuff[100];
, но вы не должны полагаться на него.