Obviously printf and fprintf (vprintf and vfprintf) use malloc but sprintf and snprintf (vsprintf and vsnprintf) don't. strdup does as per specified by its contract as a chained call of malloc and memmove. Some implementation of sscanf (vsscanf) uses malloc for internal buffers, and if so through that fscanf and scanf (vfscanf and vscanf) will also use malloc.
Obviously printf and fprintf (vprintf and vfprintf) use malloc but sprintf and snprintf (vsprintf and vsnprintf) don't. strdup does as per specified by its contract as a chained call of malloc and memmove. Some implementation of sscanf (vsscanf) uses malloc for internal buffers, and if so through that fscanf and scanf (vfscanf and vscanf) will also use malloc.
Yes of course strdup by definition uses malloc. The OP though said STRING functions, and we can all agree that printf, sprintf, etc. are stdio.h functions
In other words, I am not convinced of the OP's claims. I think other than printf and friends, and strdup, nanolibs or any C library implementation, for that matter, should or WOULD use malloc.
*as a compiler writer, I have written my share of C library functions*
From a maintainer's aspect, using malloc in fprintf (and in turn printf) makes sense, as it means that there would be only one instance of printf code in vsnprintf and all other whatever-printf functions directly or indirectly calls it. A malloc-less version would have to include two copies of almost the same code in vsnprintf and vfprintf respectively, or use some function pointer magic and slash vsnprintf efficiency almost in half.
From a maintainer's aspect, using malloc in fprintf (and in turn printf) makes sense, as it means that there would be only one instance of printf code in vsnprintf and all other whatever-printf functions directly or indirectly calls it. A malloc-less version would have to include two copies of almost the same code in vsnprintf and vfprintf respectively, or use some function pointer magic and slash vsnprintf efficiency almost in half.
I beg to differ. They just have to call a 'putc' function instead of writing to the given buffer's current pointer and incrementing it. Just one test.
ssize_t _real_vnprintf(ssize_t limit, void (*action)(void *context, char ch), void *context, const char *format, va_list args)
{
while (...)
{
char ch;
// Actual printf code
action(context, ch);
}
}
struct _vsnprintf_context
{
char *buffer;
off_t *location;
}
void _vsnprintf_action(void *context, char ch)
{
struct _vsnprintf_context *ctx = context;
ctx->buffer[*ctx->location] = ch;
*ctx->location++;
}
ssize_t vsnprintf(char *buffer, size_t limit, const char *format, va_list args)
{
struct _vsnprintf_context ctx = {buffer, 0};
ssize_t rv = _real_vnprintf(limit, _vsnprintf_action, &ctx, format, args);
ctx.buffer[ctx.location] = 0;
return rv;
}
ssize_t vfprintf(FILE *file, const char *format, va_list args)
{
return _real_vnprintf(-1, fputc, file, format, args);
}
The overhead of calling _vsnprintf_action for each character will add up - not ideal for slow CPU. Or if _real_vnprintf is a macro the resulting code will have two copies of printf code, one for vsnprintf and one for vfprintf - not ideal when Flash memory is constrained.I can definitely think of a couple ways of implementing just one core function for all the printf() variants and use it to implement them without duplicating code. Definitely doable without code duplication.
Speaking as a compiler vendor who has multi-thousands of users since 1994 for MCU from HC11, HC08, CPU12, ARM V7, Propeller, MSP430, Cortex... we have always used a single core printf-format function and use function pointers to either write using putc, or stuff the output to a buffer, depending on whether it is printf or sprintf (and the variants).
Indeed, for the smaller MCUs, it's a worse sin to have multiple similar code functions than printf being slow as customers can easily understand that printf can be and will be slow, due to its features.
C as a language is broken anyway, why bother. Yes, you can pretend that C will be a safer with some constructions and limited subset, but nevertheless the C as a language is unsafe.
soldering irons are unsafe, there is only limited number of ways you can use one without breaking things or burning you fingers
C language is not the problem
C language is not the problem
If the C language wasn't the problem, we....
C is here to stay
C is here to stay
I am not sure about this. There are other languages in development, and for example, The Rust Programming Language is very interesting and promising
Speaking as a compiler vendor who has multi-thousands of users since 1994 for MCU from HC11, HC08, CPU12, ARM V7, Propeller, MSP430, Cortex... we have always used a single core printf-format function and use function pointers to either write using putc, or stuff the output to a buffer, depending on whether it is printf or sprintf (and the variants).
Indeed, for the smaller MCUs, it's a worse sin to have multiple similar code functions than printf being slow as customers can easily understand that printf can be and will be slow, due to its features.
Programs are written by people who know how to program.
The military and the avionic industry mandated the use of Ada in the 90s and on. People thought the era of "better software engineering" for such use would be upon us... and yet, most of those software are still and will be written using C and C++
Legacy, you just proved my point
I am not convinced of the OP's claims
I am not even convinced whatsoever than using malloc() would speed anything up in the general case compared to using function pointers and so on.