#c #string #memory
Вопрос:
Когда я запускаю следующий код:
#include <stdio.h>
#include <string.h>
int main() {
static char foo[32];
memset(foo, '0', sizeof(foo));
printf("%s %dn", foo, sizeof(foo));
return 0;
}
Я получаю следующий вывод:
00000000000000000000000000000000☺ 32
Длина строки 33, а ее размер 32 байта, поэтому кажется, что символ «смайлик» с индексом 32 взят из какого-то фрагмента нераспределенной памяти. Я в замешательстве относительно того, что здесь происходит, и, похоже, я не могу достаточно хорошо сформулировать поисковый запрос, чтобы найти то, что я ищу. Любые предложения будут высоко оценены.
Комментарии:
1. Вопрос: итак, похоже, что символ «смайлик» с индексом 32 происходит из какого-то фрагмента нераспределенной памяти.. Да. Вы инициализировали все 32 символа вашего 32-символьного массива цифрой ASCII «0» … но вы забыли обнулить завершение строки! Последний символ строки C должен быть двоичным «0». Результатом является неопределенное поведение .
2. Спасибо за помощь!
3. «Длина строки 33» —> >
foo
не является строкой , так как в ней отсутствует нулевой символ .
Ответ №1:
%s
в printf()
ожидает указатель на строки, что означает «последовательность символов, заканчивающаяся нулевым символом» в C.
Все байты в буфере foo
заполнены '0'
, поэтому в буфере нет завершающего нуль-символа, и printf()
он выйдет за пределы диапазона, чтобы найти завершающий нуль-символ.
Вы должны указать длину для печати, если хотите напечатать последовательность символов, которая не является строкой (без окончания нулевого символа).
Также обратите внимание, что sizeof
возвращает size_t
%d
спецификатор формата while и заданную длину (если она указана в качестве аргумента). Передача данных неправильного типа вызывает неопределенное поведение. Правильный спецификатор формата для печати size_t
%zu
. (Обратите внимание, что size_t
это без подписи).
#include <stdio.h>
#include <string.h>
int main() {
static char foo[32];
memset(foo, '0', sizeof(foo));
printf("%.*s %zun", (int)sizeof(foo), foo, sizeof(foo));
return 0;
}
Комментарии:
1. Спасибо за ответ! Я подозревал, что это как-то связано с завершающим символом в строке, но я не мог точно определить его. Кстати, почему этот ответ отвергается?
2. @SeanXie NMDV, все же я подозреваю, что печать массива символов с
"%.*s"
помощью необычна для некоторых. Это правильное решение для 32-байтового массива с 32'0'
. Альтернативы включают созданиеfoo[33];
строки и использование"%s"
.