- 1
sprintf(path, "/usr/local/something/something_else_%d_%d.uyvy%c", some_int, some_other_int, '\0');
Нашли или выдавили из себя код, который нельзя назвать нормальным, на который без улыбки не взглянешь? Не торопитесь его удалять или рефакторить, — запостите его на говнокод.ру, посмеёмся вместе!
+143
sprintf(path, "/usr/local/something/something_else_%d_%d.uyvy%c", some_int, some_other_int, '\0');
Мда-с.
Говно.
Откуда компилятору знать реальные ограничения на размер буфера? В некоторых случаях он может, конечно, определить размер (если пишем в массив фиксированного размера внутри текущего скопа), в общем же случае это сделать невозможно.
На этапе компиляции существует алгоритм вычисления размера блока на этапе исполнения.
Я думаю это будет уже не сишка. Ну в смысле полагаться на UB умного компилятора совершенно непортабельный способ.
> не сишка
А для debug-версии - идеал.
Запустил, посмотрел, исправил и скомпилировал оптимизированную версию.
>Запустил, посмотрел, исправил и скомпилировал оптимизированную версию.
Ну во-первых как правильно сказано выше дебаг это и сделает, а во-вторых запилены всякого рода санитайзеры, с кучей проверок.
... если известно начало блока. Но sprintf же и в таком коде юзают: Вычисли-ка, сколько байт осталось в блоке, на середину которого ссылается buf.
P.S. Рантайм D это как-то делает, но там, емнип, специальный навороченный аллокатор, рассчитанный на это. Для сишки это будет оверкиллом.
P.S. Для любителей комфорта и безопасности есть два решения - качать/писать нормальную либу для работы со строками или уходить на другой, более высокоуровневый, язык.
Не, можно отдельно хранить размер и как-то его спрашивать, но это уже не сишка.
К примеру, в ней есть localtime и gmtime, но в обратную сторону есть только mktime, который... работает только с локальной tz, а варианта для utc тупо нет! Каким местом надо было думать, чтобы такое сделать и за столько лет не исправить? Я уж не говорю о работе с произвольной tz.
Rust,
(OCaml)
И код переписывать не надо.
Я не спорю, это полезная фича. Но проблему sprintf'а и прочего говна она совершенно не решает, а только загоняет под ковёр.
> почему юзер должен страдать хуйней...
...и писать на сишке, когда вокруг есть столько высокоуровневых языков.
Лол, блять. Ну держи, фома неверующий:
Т.е. вижуалка в таком коде всяко не будет делать замену sprintf на snprintf. Максимум какой-нибудь ворнинг кинет или ошибку.
P.S. Емнип, она вообще sprintf и прочие подобные функции обзывала deprecated и заставляла юзать свои альтернативные версии (которые как раз проверяют длину).
Это таки для cpp. Ну значит нехуй летать в нашем небе писать на си.
Спасибо, значит память меня не подвела.
1) sprintf они считают deprecated и показывают предупреждение (и правильно делают!)
2) sprintf_s для сишки всегда требует указывать размер буфера вручную, как и snprintf из C99
3) sprintf_s для крестов для простых случаев типа char s[10] считает этот размер сам, в остальных же - требует указывать размер вручную
Если ему наврать и передать неправильный размер - запросто приведёт. Если же размер передан правильно - всё будет ок, просто строка обрежется под размер буфера (об этом можно узнать по возвращаемому snprintf'ом значению).
Известной в статике?
Да, известной на момент компиляции. С VLA (variable length array) тоже работает, но VLA - это гццизм, на него можешь не обращать внимания.
sizeof(str) - размер указателя, sizeof(*str) - размер чара - ровно 1.
Размер блока есть, как пишут выше, у аллокатора и программиста.
Вижу, Борманд уже написал, но не пропадать же добру. Запощу.