Почему при копировании определенного размера буфера с помощью memcpy и sprintf в новом буфере выводится больше символов, чем в исходном буфере?

#c #buffer

Вопрос:

У меня есть вопрос общего понимания! Вот мой код:

 #include <stdio.h> #include <unistd.h> #include <stdlib.h> #include <cstring>  int main() {  // read user input  char input[64] = {0};  read(0, input, 64);  printf("You've entered ");  printf(input);   char newbuf[128];  char smallbuf[8];   // copy into smallbuf 8 bytes of input  memcpy(smallbuf, input, 8);   // send smallbuf of 8 bytes as string into newbuf  sprintf(newbuf, "%s", smallbuf);   // print newbuf  printf(amp;newbuf[0]);   return 0; }  

Поведение, которое я получаю с 7 символами, в порядке, оно выводит 7 символов:

 $ gcc a.cpp -o a.out amp;amp; ./a.out 1234567 You've entered 1234567 1234567 1234567  

Но с 8 символами он печатает их намного больше, и мне интересно, почему он это делает:

 $ gcc a.cpp -o a.out amp;amp; ./a.out  12345678 You've entered 12345678 1234567812345678  

Спасибо, что объяснили мне! 🙂

Комментарии:

1. строки имеют значение null, чтобы отметить конец. Если вы не скопируете значение null, строка не будет завершена

2. @stark означает ли это, что если мы запишем n-1 символов в качестве входных данных, то, когда мы нажмем enter, будет скопирован нулевой символ завершения, но когда мы напишем ровно n символов, где n-размер байтов для копирования, мы опустим нулевой символ завершения, потому что мы перезаписываем его последним символом ввода?

3. При вызове нет завершающего нулевого символа read . Вы обошли эту проблему, инициализировав свой input массив со всеми 0, но затем проблема поднимается, когда вы пишете в smallbuf и newbuf .

4. Кроме того, пожалуйста, никогда не пишите такие вещи, как printf(amp;newbuf[0]) . Если пользователю случится ввести строку, содержащую один % или два знака, произойдут сумасшедшие вещи! Всегда печатайте строки с помощью printf("%s", amp;newbuf[0]) , или puts(amp;newbuf[0]) . (И в этом случае вам может сойти с printf("%s", newbuf) рук , или puts(newbuf) . )

5. memcpy не знает о строках. Взгляните на веревочку. функции h.

Ответ №1:

Код пытается напечатать массив символов, как если бы это была строка, приводящая к неопределенному поведению. smallbuf[] определенно не содержит нулевого символа, поэтому это не строка.
"%s" ожидает соответствующий указатель на строку.

Либо учитывайте нулевой символ

 char smallbuf[8 1]; memcpy(smallbuf, input, 8); smallbuf[8] = ''; printf("%s", smallbuf);  

или ограничьте выход с определенной точностью. Это выводит массив символов до N символов или нулевой символ.

 char smallbuf[8]; memcpy(smallbuf, input, 8); printf("%.8s", smallbuf);  

Аналогичная проблема относится и к printf(input);


Не кодируйте printf(input); , так как это может привести к неопределенному поведению, когда input[] содержит a % .

 // printf(input); printf("%s", input);  

Лучший код проверил бы возвращаемое значение read(0, input, 64) .