Не совсем правильно.Вам не нужно очищать весь массив redponseData
- достаточно просто очистить его первый байт:
responseData[0] = 0;
Как отмечает Габриэль Пеллегрино в комментарии , более идиоматическое выражение
responseData[0] = '\0';
Он явно определяет символ через его кодовую точку с нулевым значением, тогда как первый использует int
постоянный ноль.В обоих случаях правый аргумент имеет тип int
, который неявно преобразуется (усекается) в тип char
для присваивания.(Пункт зафиксировал thx в комментарии pmg .)
Вы можете знать, что из документации strcat
: функция добавляет свою вторую строку аргумента к первой,Если вам нужен самый первый блок для получения сохраненного в буфер, вы хотите добавить его в пустую строку, поэтому вы должны убедиться, что строка в буфере пуста.То есть он состоит только из завершающего символа NUL.memset
- весь массив - это избыточное убийство, а значит, трата времени.
Кроме того, использование strlen
для массива вызывает проблемы.Вы не можете знать, каково фактическое содержимое блока памяти, выделенного для массива.Если он еще не использовался или был перезаписан какими-либо другими данными со времени вашего последнего использования, он может содержать без NUL-символа.Тогда strlen
выйдет из массива, что приведет к неопределенному поведению.И даже если он вернется успешно, он даст вам длину строки больше, чем размер массива.В результате memset
выйдет из массива, возможно, перезаписывая некоторые важные данные!
Используйте sizeof всякий раз, когда вы memset
массиве!
memset(responseData, 0, sizeof(responseData));
РЕДАКТИРОВАТЬ
Выше я пытался объяснить, как исправить проблему с вашим кодом, но я не ответил на ваши вопросы.Вот они:
- Почему переменным (...) в разных областях назначаются одинаковые адреса памяти?
В отношении выполнениякаждая итерация цикла while(1) { ... }
действительно создает новую область видимости.Однако каждая область видимости завершается до создания новой области, поэтому компилятор резервирует соответствующий блок памяти в стеке, и цикл повторно использует его в каждой итерации.Это также упрощает скомпилированный код: каждая итерация выполняется точно таким же кодом, который просто переходит с конца на начало.Все инструкции в цикле, которые обращаются к локальным переменным, используют одну и ту же адресацию (относительно стека) в каждой итерации.Таким образом, каждая переменная в следующей итерации имеет точно такое же место в памяти, как и во всех предыдущих итерациях.
Я обнаружил, что мне нужно вручную очистить память Да, автоматические переменные, расположенные в стеке, не инициализированы в Cпо умолчанию.Нам всегда нужно явно присваивать начальное значение, прежде чем мы его используем - в противном случае значение не определено и может быть неправильным (например, переменная с плавающей запятой может отображаться не как число, массив символов может показаться не завершенным, *Переменная 1062 * может иметь значение вне определения enum, переменная-указатель может не указывать на допустимое, доступное местоположение и т. Д.).
в противном случае содержимое (...) просто непрерывно добавляется На этот вопрос был дан ответ выше.
Исходя из JavaScript, это было удивительно Да, JavaScript, очевидно, создает новых переменных в новой области видимости, следовательно, каждый раз, когда вы получаете брендновый массив - и он пуст.В C вы просто получаете ту же область ранее выделенной памяти для автоматической переменной, и вы обязаны ее инициализировать.
Кроме того, рассмотрите два последовательных цикла:
void test()
{
int i;
for (i=0; i<5; i++) {
char buf1[10];
sprintf(buf1, "%d", i);
}
for (i=0; i<1; i++) {
char buf2[10];
printf("%s\n", buf2);
}
}
Первыйодин печатает однозначное символьное представление пяти чисел в массив символов, перезаписывая его каждый раз - следовательно, последнее значение buf1[]
(в виде строки) равно "4"
.
Какой выход вы ожидаете от второго цикла? Вообще говоря, мы не можем знать, что будет содержать buf2[]
, и printf
-ing вызывает UB. Однако мы можем предположить, что один и тот же набор переменных (а именно один массив символов из 10 элементов) из обеих непересекающихся областей будет распределен одинаково в одной и той же части стека. Если это так, мы получим цифру 4
в качестве вывода из (формально неинициализированного) массива.
Этот результат зависит от конструкции компилятора и должен рассматриваться как совпадение. Не надейтесь на это, так как это UB!
- Почему бы C просто не сбросить память за кулисами?
Потому что это не сказано. Язык был создан для компиляции в эффективный, компактный код. Это делает как можно меньше «за кадром». Среди прочих вещей, которые он не делает, не инициализирует автоматические переменные, если это не указано. Это означает, что вам нужно добавить явный инициализатор в объявление локальной переменной или добавить инструкцию инициализации (например, присваивание) перед первым использованием. (Это не относится к глобальным переменным области модуля; по умолчанию они инициализируются нулями.)
В языках более высокого уровня некоторые или все переменные инициализируются при создании, но не в C. Это его особенность, и мы должны жить с этим - или просто не использовать этот язык.