Модераторы: Daevaorn
  

Поиск:

Ответ в темуСоздание новой темы Создание опроса
> sprintf и нулевой символ 
V
    Опции темы
Fedor
Дата 6.1.2007, 13:57 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Днепрянин
****


Профиль
Группа: Участник
Сообщений: 2090
Регистрация: 8.2.2003
Где: Великий

Репутация: нет
Всего: 32



Рассмотрим простенький примерчик:
Код

#include <stdio.h>
void main()
{
   char a = '\0';
   char buf[100];

   printf( "printf: %0cTest\n", a );
   sprintf( buf, " sprintf: %0cTest2\n", a );
   printf( "%s", buf );
}

Компилим например в cc, gcc, xLc, etc.

В случае printf нулевой символ пропускается, и слово Test выводится на ура.
В случае sprintf, нулевой символ пишется в buf, и соответственно на экран все что за ним не выводится.

В общем, что сие? Почему различия в поведении? Баг, фича, что-то еще? В стандарте С что-нибудь сказано по сему поводу?


--------------------
Мы - Днепряне. Мы всех сильней.
PM ICQ   Вверх
Sartorius
Дата 6.1.2007, 14:06 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
***


Профиль
Группа: Завсегдатай
Сообщений: 1568
Регистрация: 18.7.2006
Где: Ivory tower

Репутация: 8
Всего: 37



 ИМХО не баг и не фича. В первом случае format string должна пропарситься целиком, независимо от того , что будет выводиться. А во втором случае - нопмальный вывод zerro-string . Усе логично.

ЗЫ не следует думать, что при printf сначала формируется где то буффер , содержащий вывод, а потом выводится эта строка

Это сообщение отредактировал(а) Sartorius - 6.1.2007, 14:07
PM MAIL ICQ   Вверх
WERITAS
Дата 6.1.2007, 14:14 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


********
**


Профиль
Группа: Участник
Сообщений: 582
Регистрация: 2.5.2005
Где: Москва

Репутация: нет
Всего: 5



Код

В случае printf нулевой символ пропускается, и слово Test выводится на ура.
В случае sprintf, нулевой символ пишется в buf, и соответственно на экран все что за ним не выводится.


Все правильно! На то он и нулевой символ. 
printf выводит строчку на экран. Там не обрывается вывод. Так и надо.  А в другом случае  sprintf копирует в буфер.  Т.е. ты конец строки вставил в начало строки, поэтому ничего и не выводится.


О5 опередили!  smile 

Это сообщение отредактировал(а) WERITAS - 6.1.2007, 14:15


--------------------
Арт-менеджер клуба, разрешивший концерт Алексея Глызина, уволен с формулировкой "Мудак"
PM MAIL   Вверх
W4FhLF
Дата 6.1.2007, 14:28 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


found myself
****


Профиль
Группа: Участник Клуба
Сообщений: 2831
Регистрация: 2.12.2006

Репутация: 20
Всего: 121



Цитата(Fedor @  6.1.2007,  13:57 Найти цитируемый пост)
В общем, что сие? Почему различия в поведении? Баг, фича, что-то еще? В стандарте С что-нибудь сказано по сему поводу?


Не знаю как насчёт стандарта, но вот 10 минут в отладчике помогли сделать такие выводы:


Цитата

printf( "printf: %0cTest\n", a );


Функция СНАЧАЛА определяет длину формата(т.е. printf: %0cTest\n), она равна 0xE, ПОСЛЕ чего она делает подстановку всех переменных. Т.е. на этом этапе мы имеем в буфере:

Цитата

00155170  70 72 69 6E 74 66 3A 20 00 54 65 73 74 0A        printf: .Test.


И в функцию CRTDLL._write передаётся указатель на буфер и длина ФОРМАТА, т.е. 0xE, а не 0x8 как может показаться. 

Цитата

sprintf( buf, " sprintf: %0cTest2\n", a );


Определяется длина формата, идёт подстановка переменных и копирование в буфер того кол-ва байт, которое равно длине формата.

Цитата

printf( "%s", buf );


При парсинге формата программа находит %s, далее программа берёт первую переменную из списка, т.е. buf и определяет её длину путём поиска \0 в строке, именно эта величина считается размером буфера при передаче параметров функции CRTDLL._write, любой текст после символа \0 не учитывается, т.к. концов строки(%s) является именно он.

Ну так, в общих чертах, что непонятно спрашивайтеsmile

Добавлено @ 14:28 
Опередили засранцыsmile


--------------------
"Бог умер" © Ницше
"Ницше умер" © Бог
PM ICQ   Вверх
Fedor
Дата 6.1.2007, 15:08 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Днепрянин
****


Профиль
Группа: Участник
Сообщений: 2090
Регистрация: 8.2.2003
Где: Великий

Репутация: нет
Всего: 32



Sartorius, WERITAS, W4FhLF, всем спасибо. Логику осознал.


--------------------
Мы - Днепряне. Мы всех сильней.
PM ICQ   Вверх
  
Ответ в темуСоздание новой темы Создание опроса
Правила форума "С++:Общие вопросы"
Earnest Daevaorn

Добро пожаловать!

  • Черновик стандарта C++ (за октябрь 2005) можно скачать с этого сайта. Прямая ссылка на файл черновика(4.4мб).
  • Черновик стандарта C (за сентябрь 2005) можно скачать с этого сайта. Прямая ссылка на файл черновика (3.4мб).
  • Прежде чем задать вопрос, прочтите это и/или это!
  • Здесь хранится весь мировой запас ссылок на документы, связанные с C++ :)
  • Не брезгуйте пользоваться тегами [code=cpp][/code].
  • Пожалуйста, не просите написать за вас программы в этом разделе - для этого существует "Центр Помощи".
  • C++ FAQ

Если Вам понравилась атмосфера форума, заходите к нам чаще! С уважением, Earnest Daevaorn

 
0 Пользователей читают эту тему (0 Гостей и 0 Скрытых Пользователей)
0 Пользователей:
« Предыдущая тема | C/C++: Общие вопросы | Следующая тема »


 




[ Время генерации скрипта: 0.0449 ]   [ Использовано запросов: 22 ]   [ GZIP включён ]


Реклама на сайте     Информационное спонсорство

 
По вопросам размещения рекламы пишите на vladimir(sobaka)vingrad.ru
Отказ от ответственности     Powered by Invision Power Board(R) 1.3 © 2003  IPS, Inc.