sprintf возится с моими указателями и данными?

#c

#c

Вопрос:

 char purl[1024];
unsigned char * puMember;
unsigned char uMember;
puMember = amp;uMember;

unsigned char * pMember;
unsigned char Member;
pMember = amp;Member;

printf("member: %sn",pMember);
printf("username :%sn",puMember);
sprintf(purl, "Username: %s %s",puMember,pMember);
printf("URL:%sn",purl);
printf("member: %sn",puMember);
printf("username :%sn",pMember);
  

Вывод

 member: 12345678
username :User1
URL: username: cUser1 ser1
member: User1
username :ser1
  

Я не понимаю, почему sprintf портит мои указатели после их выполнения.

У pMember есть 12345678, а у puMember есть User1, я пытаюсь отформатировать их в строку (purl), но, похоже, sprintf их путает :/

Любая помощь, как я мог бы это сделать?

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

1. Как выглядят определения этих переменных? Я подозреваю, что вы переполняетесь purl .

2. нам нужны определения pMember , puMember , purl ; и если это не составит особого труда pUserID и pMemberID . Спасибо

3. добавлено немного больше информации, надеюсь, это поможет

4. Стилистический комментарий — не используйте временные обозначения для указателей на переменные, за этим трудно уследить. Используйте amp;var вместо этого.

Ответ №1:

Ваш код очень странный — если pMember и puMember указывают на отдельные символы, почему printf они в виде строки, завершающейся mull? Он будет печатать что угодно, пока не найдет null в памяти.

Аналогично, sprintf будет продолжать считывать память после символов Member и uMember и заполняться purl — в зависимости от того, когда он найдет нулевой байт в памяти.

Использование snprintf вместо printf позволит избежать переполнения буфера, но чего именно вы пытаетесь достичь?

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

1. Ну, я печатаю их, потому что я заполнил оба из них значением, а последний символ [] равен », так что это printf без каких-либо проблем. Я пытаюсь получить purl в виде строки, равной «Username: 123456789, User1», передавая 2 переменные для создания такого типа строки, поскольку это все меняет.

2. Member и uMember содержит только 1 символ. Как вы можете «заполнить их», плюс добавить завершающий null? Что вы на самом деле делаете, так это перезаписываете смежную память.

3. Я понимаю, что ты имеешь в виду! Я редактировал указатель и добавлял символы и не понимал, что это не выделенная мне память, а запись в другом месте. Спасибо

Ответ №2:

 char purl[1024];
unsigned char * puMember;
unsigned char uMember;
  

uMember имеет пробел для 1 символа; 'F' или '4' или ''

 puMember = amp;uMember;
  

puMember указывает на этот символ. И только этот символ: размер объекта составляет 1 байт.

 unsigned char * pMember;
unsigned char Member;
  

Member есть пробел для 1 символа

 pMember = amp;Member;
  

pMember указывает на 1 символ.

 printf("member: %sn",pMember);
  

Нет, нет, нет. pMember не указывает на «строку». Вы вызвали неопределенное поведение: может произойти все, что угодно

 printf("username :%sn",puMember);
  

Нет, нет, нет. puMember не указывает на «строку». Вы вызвали неопределенное поведение: может произойти все, что угодно

 sprintf(purl, "Username: %s %s",puMember,pMember);
  

Нет, нет, нет. puMember и pMember не указывают на «string»ы. Вы вызвали неопределенное поведение: может произойти все, что угодно

 printf("URL:%sn",purl);
printf("member: %sn",puMember);
printf("username :%sn",pMember);
  

Нет, нет, нет …

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

1. Это неопределенное поведение или непредсказуемое поведение? printf и sprintf следует продолжать чтение символов, пока они не достигнут значения null.

2. Это неопределенное поведение. Предположим, что символ находится на границе «чего-то», и пересечение этой границы запускает самоуничтожение. выполнение printf("%sn", pMember); может быть таким же, как selfdestruct(SELFDESTRUCT_IMMED); 🙂

Ответ №3:

Вы где-то перезаписываете буфер. Замените sprintf на snprintf , чтобы библиотека C точно знала, сколько места у вас есть в целевом буфере, например:

 char buffer[32];
snprintf( buffer, 32, "my text: %sn", some_char_ptr );
  

Редактировать 0:

Строки в C заканчиваются нулем, что означает, что в конце блока памяти есть один дополнительный байт, который имеет значение '' и который сигнализирует о конце строки. Это то, что библиотека C предполагает для строковых функций, таких как strlen и strcpy , и для %s спецификатора формата для всех printf . В противном случае эти библиотечные функции будут работать в памяти до тех пор, пока не будет найден байт с нулевым значением или ОС не убьет вашу программу для доступа к незамеченной памяти.

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

1. 1 — sprintf в производственном коде ошибка, всегда используйте snprintf

2. snprintf имеет свое применение. Я не понимаю, как это здесь помогает 😉 — Поскольку это вынуждает вас использовать компилятор C99, это может быть даже контрпродуктивно.

3. @pmg — это позволяет избежать одной проблемы, в частности переполнения буфера.

4. Прежде чем беспокоиться о переполнении буфера, оператору следует побеспокоиться о том, чтобы не обрабатывать случайные char файлы в памяти как «строковые» 🙂 — и в исходном коде переполнения буфера не было: в purl массиве есть место для 1024 символов.

5. Я бы сказал, что snprintf в производственном коде также является ошибкой, если только вы не имеете дело с большим количеством форматирования с плавающей запятой в строку. s * printf не только занимает огромные объемы памяти, но и работает очень медленно. Если вы выполняете только преобразование int-to-string / строка-в-int, напишите для этого свои собственные процедуры. 30 минут работы, а затем вы повторно используете их во всех своих проектах программирования в будущем.