Завершенная нулем строка в C - PullRequest
1 голос
/ 20 ноября 2011

Я очень беспокоюсь о строках в C. Нужно ли устанавливать последний символ \ 0, или он делает это сам?Если я не делаю это вручную, тогда, когда я пытаюсь отладить код и когда я получаю доступ к string1 [257], он не равен нулю.У меня проблемы с освобождением выделенной памяти массива строк, поэтому я подумал, что это причина.

char string1[257], string2[257];
scanf("%s", &string2);
string1[257] = '\0';
strncpy(string1, string2, 257);
string1[257] = '\0'; /* do I need to do that? */

Ответы [ 5 ]

1 голос
/ 20 ноября 2011

Всегда будьте осторожны, чтобы выделить достаточно памяти для строк, сравните эффекты следующих строк кода:

char s1[3] = "abc";
char s2[4] = "abc";
char s3[] = "abc";

Все три считаются допустимыми строками кода (http://c -faq.com / ansi / nonstrings.html http://c -faq.com / ansi / nonstrings.html ), но в первом В этом случае недостаточно памяти для четвертого символа с нулевым символом в конце. s1 не будет вести себя как обычная строка, но s2 и s3 будут. Компилятор автоматически считает s3, и вы получаете четыре байта выделенной памяти. Если вы попытаетесь написать

s1[3] = '\0';

это неопределенное поведение, и вы пишете в память, которая не принадлежит s1, и может привести к странным эффектам, возможно, даже нарушая внутреннюю информацию malloc, затрудняя освобождение памяти.

1 голос
/ 20 ноября 2011

Это абсолютно необходимо? Нет , потому что когда вы вызываете scanf, strcpy (за исключением strncpy, где вам нужно вручную поставить ноль, если он превышает размер), он копирует нулевой терминатор для вас.Хорошо ли это делать в любом случае? Не совсем , это не очень помогает проблеме переполнения буфера, так как эти функции в любом случае будут превышать размер буфера.Тогда как лучше?используйте c ++ с std::string.

Кстати, если вы обращаетесь к string1[257] / записываете его, это будет вне пределов, так как вы получаете доступ / записываете элемент 258 массив размером 257. (индекс на основе 0)

1 голос
/ 20 ноября 2011

Литеральная строка типа "foo\nbar" всегда переводится в const char literal[] с дополнительным нулевым байтом в конце. (Таким образом, константа будет иметь 8 байтов, первый из которых будет f, а последний равен нулю).

Но вы правы в явном приведении последнего байта к 0 после strncpy.

И, как заметил Аурелио Де Роса, последний правильный индекс равен 256 для массива [257].

1 голос
/ 20 ноября 2011

Да, вам нужно это сделать. Не все функции ставят для вас пустой символ, и strncpy, как я могу прочитать на его странице руководства, требует наличия нулевого байта среди первых n символов src.

1 голос
/ 20 ноября 2011

Строковые литералы, такие как "Hello World!", заканчиваются нулем, но char массивы автоматически не заканчиваются нулем.

Общий принцип, который я всегда придерживался, это быть очень осторожным и присваивать '\0' концу строки, если это не вызывает проблем с производительностью. В этих случаях я очень осторожен с тем, какие библиотечные функции я использую.

...