2014-08-28 4 views
7

В последнее время я заметил странное дело, я хотел бы проверить:символы, написанные до сих пор в snprintf

По SUS для %n в строке формата, соответствующий int будет установлен на-сумму-в-байт -written-к-вывода. Кроме того, для snprintf(dest, 3, "abcd"), dest укажет на "ab\0". Зачем? Потому что на выходе должно быть записано не более n (n = 3) байтов (буфер dest).

Я сделал вывод, что для кода:

int written; 
char dest[3]; 
snprintf(dest, 3, "abcde%n", &written); 

written будет установлен в 2 (нулевое значение прекращения исключены из подсчета). Но из теста, который я сделал с использованием GCC 4.8.1, written, было установлено значение 5. Был ли я неверным толкованием стандарта? Это ошибка? Это неопределенное поведение?

Edit:

@wildplasser сказал:

... поведение% п в строке формата может быть определено или определено осуществление ...

И

... реализация должна моделировать обработку полной строки формата (включая% n) ...

@par сказал:

written является 5, потому что это, сколько символов будет записано в точке %n встречается. Это правильное поведение. snprintf копирует только до size символов минус завершающим нулем ...

И:

Другой способ смотреть на это, что %n бы не даже встречались, если она обрабатывается только вверх 2 символов, так что возможно ожидать written иметь недопустимое значение ...

И:

... вся строка обрабатывается с помощью printf() правил, затем максимальная длина применяется ...

Можно ли проверить быть стандартом, стандарт-проект или какой-либо официальный источник?

+0

Похож на ошибку (в реализации библиотеки) для меня. – pmg

+1

Я ожидаю, что вы должны * сначала посмотреть на возвращаемое значение из snprintf(). «Побочные эффекты» различны; поведение '% n' в строке формата может быть неопределенным или определена реализация, если returnvalue => 2-й аргумент. В любом случае реализация должна * имитировать * обработку строки * полного * формата (включая '% n') для получения правильного возвращаемого значения, поэтому побочный эффект можно получить« на лету ». – wildplasser

ответ

7

written - 5, потому что это количество символов будет записано в точке, где встречается %n. Это правильное поведение. snprintf только копии до size символов минус конечный нуль (так что в вашем случае 3-1 == 2. Вам нужно отделить поведение форматирования строк от символов только для записи столько-то.

Другой способ взглянуть на это состоит в том, что %n даже не столкнулся бы, если он обрабатывал только до двух символов, поэтому можно ожидать, что written будет иметь недопустимое значение. Вот где будет ошибка, если бы вы ожидали чего-то действительного в written в точке %n (и не было).

Так что помните, что вся строка обрабатывается с помощью printf() правил, затем применяется максимальная длина.

+1

Хммм, текст Стандарта содержит ** «... количество символов, записанных в выходной поток до сих пор ...» **; '' c'', '' d'' и '' e'' не были записаны в выходной поток – pmg

+1

@pmg - символы * были * записаны в выходной поток, поскольку выходной поток является буфером данных " за кулисами "в функции printf(). * Затем * происходит действие snprintf только для копирования символов размера из «выходного потока». См. Ответ Хайнца для ссылки на ISOC99. – par

+1

, то, опять же, текст, относящийся к ''% n "', не относится к 'sprintf()', потому что эта функция не записывается в выходные потоки. – pmg

5

Это не ошибка: ISOC99 говорит

Функция snprintf эквивалентна fprintf [...] выходные символы за пределами п-1, отбрасываются, а не записываются в массив [ ...]

Поэтому он просто отбрасывает выходной результат, но в противном случае ведет себя одинаково.

Смежные вопросы