Perché restituire un puntatore statico invece di un parametro out?

Perché restituire un puntatore statico invece di un parametro out?

La specifica del ctime e asctime le funzioni risalgono al C89 e le cose erano fatte in modo leggermente diverso a quei tempi, principalmente perché i sistemi multiprocessore non erano molto comuni e quindi l'utilizzo di un buffer statico non avrebbe causato grossi problemi.

Molto probabilmente, non hanno restituito la memoria allocata dinamicamente perché richiedeva più tempo e in quei giorni i cicli della CPU erano più difficili da trovare.

Se sei su un sistema POSIX come Linux, hai altre due funzioni disponibili che sono sostanzialmente quelle che hai descritto come un'alternativa:

   char *asctime_r(const struct tm *tm, char *buf);
   char *ctime_r(const time_t *timep, char *buf);

Queste funzioni prendono un puntatore a un buffer che può ricevere l'output (e restituiscono un puntatore a quello stesso buffer). Il _r suffisso significa "rientrante", il che significa che può essere tranquillamente chiamato in un programma multithread o più di una volta senza un punto di sequenza nel mezzo.


Perché devi copiarlo?

Nota che anche se copi i dati non appena li ottieni, sarai comunque aperto alle gare.

Perché quando sono stati standardizzati (1989), la maggior parte dei software non era multi-thread anche se il multi-thread esisteva sin dall'era dei mainframe. Per riferimento, anche i thread POSIX sono stati standardizzati anni dopo (1996) rispetto a queste funzioni. Non ha aiutato nemmeno il fatto che i computer diventassero più veloci ogni anno e che i processori multi-core/SMT non siano comparsi fino al 2001-2006.

Se hai bisogno di qualcos'altro, puoi sempre usare una funzione specifica del sistema.

L'assegnazione è molto costosa.

Non sono sicuro di cosa intendi con questo. Il modo corretto per farlo è passare un puntatore al buffer di destinazione, in modo che l'utente scelga quale metodo di allocazione utilizzare.


Stai (quasi) descrivendo il _s varianti che sono state aggiunte in C11

errno_t ctime_s(char *buffer, rsize_t bufsz, const time_t *time);
errno_t asctime_s(char *buf, rsize_t bufsz, const struct tm *time_ptr);

Questi scrivono nella posizione specificata, a condizione che sia sufficientemente grande, e segnalano l'errore in caso contrario.

Non è necessario malloc i buffer per queste chiamate, come sai char buf[26]; è esattamente ciò che serve.