2 ms·
It's pretty lame that ISO C doesn't provide integer-to-string conversion that does not go through a printf-family formatter, so that programs are still rolling
by kazinator 2y ago
It's pretty lame that ISO C doesn't provide integer-to-string conversion that does not go through a printf-family formatter, so that programs are still rolling their own "itoa" as the calendar turns to 2025.
Format strings are compilable in principle, so that:
snprintf(buf, sizeof buf, "%ld", long_value);
can just turn into some compiler-specific run-time function. The compiler also can tell when the buffer is obviously large enough to hold any possible value, and use a function that doesn't need the size.
How common is that, though?
Common Lisp's format function can accept a function instead of a format string. The arguments are passed to that function and it is assumed to do the job:
(format t (lambda (...) ...) args ...)
There is a macro called formatter which takes a format string, and compiles it to such a function.
[8]> (format t "~1,05f" pi)
3.14159
NIL
[9]> (format t "~10,5f" pi)
3.14159
NIL
[10]> (format t (formatter "~10,5f") pi)
3.14159
NIL
[11]> (macroexpand '(formatter "~10,5F"))
#'(LAMBDA (STREAM #:ARG3345 &REST #:ARGS3342) (DECLARE (IGNORABLE STREAM))
(LET ((SYSTEM::*FORMAT-CS* NIL)) (DECLARE (IGNORABLE #:ARG3345 #:ARGS3342))
(SYSTEM::DO-FORMAT-FIXED-FLOAT STREAM NIL NIL 10 5 NIL NIL NIL #:ARG3345) #:ARGS3342)) ;
T
In this implementation, formatter takes "~10,5f" and spins it into a (system::do-format-fixed-float ...) call where the field width and precision arguments are constants. Just the stream and numeric argument are passed in, along with a bunch of other arguments that are defaulted to nil.
I think CL implementations are allowed to apply formatter implicitly, which would make sense at least in code compiled for speed.
Just think: this stuff existed before there was a GNU C compiler. It was a huge progress when it started diagnosing mismatches between format strings literal and printf arguments.