*char заканчивается двойным '\0'

Мой код дает сбой из-за отсутствия символа '\0' в конце некоторых строк.

Мне совершенно ясно, почему мы должны использовать этот завершающий символ. Мой вопрос: есть ли проблема с добавлением потенциального второго нулевого символа в массив символов - для решения проблем со строками?

Я думаю, что дешевле просто добавить '\ 0' к каждой строке, чем проверять, нужно ли это, а затем добавлять ее, но я не знаю, хорошо ли это делать.


person Rômulo M. Farias    schedule 09.06.2017    source источник
comment
Наличие '\0' не является проблемой, если только вы не вышли за пределы этого массива символов. Вы должны понимать, что наличие '\0' дважды означает, что любая строковая операция даже не будет знать, что есть второй '\0'. Они будут просто читать до первого '\0' и быть с ним.   -  person Haris    schedule 09.06.2017
comment
Символ '\0' (или NUL) завершает строку. Таким образом, по определению все, что идет после этого символа NUL, не является частью строки, несмотря ни на что.   -  person Jabberwocky    schedule 09.06.2017
comment
@ RômuloM.Farias понял это после нажатия клавиши ввода :)   -  person Haris    schedule 09.06.2017
comment
Лучше правильно решить проблему и выяснить, почему некоторые из ваших строк не завершаются должным образом. Двойные нули не причинят большого вреда, но сделают обслуживание головной болью.   -  person Malcolm McLean    schedule 09.06.2017
comment
То, что вы предлагаете, является плохой практикой. Просто создайте строки правильно, во-первых, с разделителем NUL, точкой.   -  person Jabberwocky    schedule 09.06.2017
comment
Как вы проверяете, есть ли в строке \0 в конце или нет? Это невозможно сделать.   -  person Spikatrix    schedule 09.06.2017
comment
Я с @MalcolmMcLean -- если вы находитесь в ситуации, когда вы думаете, решение состоит в том, чтобы везде добавлять '\0' (кстати, как вам узнать, где заканчивается строка без '\0'?), на самом деле у вас может быть xy-проблема   -  person    schedule 09.06.2017
comment
@CoolGuy Деталь: в C строка всегда заканчивается нулевым символом. Массив символов может не иметь '\0'.   -  person chux - Reinstate Monica    schedule 09.06.2017
comment
Я не буду добавлять еще один комментарий, пытаясь убедить вас, что у вас нет проблем с ним. Вместо этого я хочу убедиться, что у вас есть проблема для одного, а не для двоих. Пожалуйста, сделайте минимально воспроизводимый пример, который демонстрирует сбой для строки без двух \0. Насколько я понимаю, у вас есть случай, который вылетает для одного \0 и не вылетает для \0\0. т.е. пожалуйста, продемонстрируйте, что он падает из-за одного \0 вместо двух, а не из-за отсутствия двух вместо двух.   -  person Yunnosch    schedule 09.06.2017
comment
@Yunnosch, извините, но проблема не в сбое с одним «\ 0». Сбой - это когда нет завершающего символа. Таким образом, мое решение всегда добавляло бы «\ 0», и когда массив символов уже имел «\ 0», он будет дублироваться. Но, прочитав некоторые ответы здесь, я решил найти основную проблему, а не просто добавить символ и сделать плохой код.   -  person Rômulo M. Farias    schedule 09.06.2017
comment
Это то, что я предполагал. Хорошее решение искать первопричину. Создание MCVE (даже если вы не собираетесь публиковать его здесь) будет идеальным способом сделать это.   -  person Yunnosch    schedule 09.06.2017


Ответы (3)


есть ли проблема иметь этот char ('\0') дважды в конце строки?

В этом вопросе нет ясности, так как "строка" означает разные вещи для людей.
Давайте воспользуемся определением спецификации C, так как это сообщение C.

строка – это непрерывная последовательность символов, заканчивающаяся первым нулевым символом и включающая его. C11 §7.1.1 1

Таким образом, строка не может содержать 2 нулевых символа, так как строка заканчивается при достижении первого символа. @Майкл Уолц

Вместо этого повторите анализ на «есть ли проблема с добавлением потенциального второго нулевого символа в массив символов - для решения проблем со строками?»


Проблема с попыткой добавить нулевой символ в строку — путаница. Функции str...() работают со строками C, как определено выше.

// If str1 was not a string, strcpy(str1, anything) would be undefined behavior.
strcpy(str1, "\0");  // no change to str1

char str2[] = "abc";
str2[strlen(str2)] = '\0'; // OK but only, re-assigns the \0 to a \0
// attempt to add another \0
str2[strlen(str2)+1] = '\0'; // Bad: assigning outside `str2[]` as the array is too small

char str3[10] = "abc";
str3[strlen(str3)+1] = '\0'; // OK, in this case
puts(str3);                  // Adding that \0 served no purpose

Как многие отмечают, добавление запасного '\0' напрямую не связано с фундаментальной проблемой кода. @Haris @Малкольм Маклин

Этот неопубликованный код является реальной проблемой, требующей решения @Yunnosch, и не пытаясь добавить второй '\0'.

person chux - Reinstate Monica    schedule 09.06.2017
comment
Я поэтому согласен, на самом деле именно поэтому я попросил MCVE с подробной проработкой деталей. Кажется, мой комментарий был не ясен. - person Yunnosch; 09.06.2017
comment
@Yunnosch Я не буду публиковать MCVE, извините за это. Код принадлежит предприятию, на котором я работаю, и я не могу этого сделать. Если вы действительно не хотите понимать, как возникает проблема, мы нашли ее с помощью Asan . Это изменяет память и нагружает мое программное обеспечение, чтобы найти потенциальные ошибки. - person Rômulo M. Farias; 09.06.2017

Я думаю, что дешевле просто добавить '\ 0' к каждой строке, чем проверять, нужно ли это, а затем добавлять ее, но я не знаю, хорошо ли это делать.

Куда бы вы его добавили? Предположим, мы сделали что-то вроде этого:

char *p = malloc(32);

Теперь, если мы знаем выделенную длину, мы можем поставить '\0' в качестве последнего символа выделенной области, как в p[31] = '\0'. Но мы не знаем, какой длины должно быть содержимое строки. Если должно быть только foobar, то все равно останется 25 байтов мусора, что может вызвать другие проблемы при обработке или печати.

Не говоря уже о том, что если все, что у вас есть, это указатель на строку, трудно узнать длину выделенной области.

Вероятно, лучше исправить места, где вы строите строки, чтобы сделать это правильно.

person ilkkachu    schedule 09.06.2017

Наличие '\0' не является проблемой, если только вы не вышли за пределы этого массива символов.

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

person Haris    schedule 09.06.2017