Domanda

Attualmente sto usando un cast esplicito a unsigned long long e utilizzando %llu stamparlo, ma dal momento che size_t ha l'identificatore %z, perché non clock_t averne uno?

Non c'è nemmeno una macro per esso. Forse posso supporre che su un sistema x64 (OS e CPU) size_t è di 8 byte di lunghezza (e anche in questo caso, hanno fornito %z), ma per quanto riguarda clock_t?

È stato utile?

Soluzione

Non sembra esserci alcun modo perfetto. La radice del problema è che clock_t può essere sia interi o in virgola mobile.

clock_t può essere un tipo a virgola mobile

Bastien Léonard menziona per POSIX (GO lo upvote), C99 N1256 progetto 7.23.1 / 3 dice anche che:

  

[clock_t è] tipi aritmetici grado di rappresentare volte

e 6.2.5 / 18:

  

integer e tipi galleggianti sono collettivamente chiamati tipi aritmetici.

e lo standard definisce tipo aritmetico sia come interi o tipi in virgola mobile.

Se si intende dividere per CLOCKS_PER_SEC, utilizzare lungo doppio

Il valore di ritorno di clock() è implementazione definita, e l'unico modo per ottenere significato standard di fuori di esso è quello di dividere per CLOCKS_PER_SEC per trovare il numero di secondi:

clock_t t0 = clock();
/* Work. */
clock_t t1 = clock();
printf("%Lf", (long double)(t1 - t0));

Questo è abbastanza buono, anche se non perfetto, per i due seguenti motivi:

  • non sembra esserci alcun analogica a intmax_t per il galleggiamento tipi di punti: Come ottenere il maggior precisione floating point tipo di dati di implemenation e il suo identificatore printf? Quindi, se un tipo in virgola mobile più grande esce domani, potrebbe essere Usato e rompere l'implementazione.

  • se clock_t è un numero intero, il cast galleggiare è ben definito per utilizzare il galleggiante più vicino possibile. Si può perdere la precisione, ma non importerebbe molto rispetto al valore assoluto, e sarebbe accadere solo per enormi quantità di tempo, per esempio long int nel x86 è il galleggiante 80-bit con 64 bit significativo, che è milioni di anni in pochi secondi.

Vai upvote Lemonad che ha detto qualcosa di simile.

Se pensate che è un numero intero, utilizzare% ju e uintmax_t

Sebbene unsigned long long è attualmente il più grande tipo intero livello possibile:

quindi è meglio typecast alla grande tipo intero senza segno possibile:

#include <stdint.h>

printf("%ju", (uintmax_t)(clock_t)1);

uintmax_t si garantisce la dimensione più grande possibile intero sulla macchina.

uintmax_t e la sua %ju printf identificatore sono stati introdotti nel C99 e gcc per esempio li implementa.

Come bonus, questo risolve una volta per tutte la questione di come affidabile printf intero tipi (che non è, purtroppo, l'necessariamente il caso per clock_t).

Che cosa potrebbe andare male se si trattava di una doppia:

  • se troppo grande per adattarsi al numero intero, un comportamento indefinito
  • molto più piccolo di 1, otterrà arrotondato a 0 e non si vede niente

Tali conseguenze sono molto più severe rispetto al numero intero di galleggiare conversione, utilizzando galleggiante è probabile un'idea migliore.

In glibc 2.21 è un numero intero

Il manuale dice che l'uso double è un'idea migliore:

  

Sui sistemi GNU / Hurd GNU / Linux e, clock_t equivale a long int e CLOCKS_PER_SEC è un valore intero. Ma in altri sistemi, sia clock_t e la macro CLOCKS_PER_SEC possono essere sia interi o tipi a virgola mobile. Casting valori di tempo di CPU per raddoppiare, come nell'esempio di cui sopra, fa in modo che le operazioni come l'aritmetica e la stampa il lavoro correttamente e del consistente me nte indipendentemente dalla rappresentazione sottostante è.

In glibc 2.21:

Vedi anche

Altri suggerimenti

Per quanto ne so, il modo in cui si sta facendo è il migliore. Solo che clock_t può essere un vero e proprio tipo:

  

time_t e clock_t sono interi o reale flottante tipi.

http://www.opengroup.org/onlinepubs/ 009695399 / basedefs / sys / types.h.html

E 'probabilmente perché clock ticks non è un'unità molto ben definito. È possibile convertirlo in secondi e stamparlo come un doppio:

time_in_seconds = (double)time_in_clock_ticks / (double)CLOCKS_PER_SEC;
printf("%g seconds", seconds);

La macro CLOCKS_PER_SEC espande un'espressione che rappresenta il numero di impulsi di clock in un secondo.

Lo standard C deve accogliere un'ampia varietà di architetture, che rende impossibile effettuare ulteriori garanzie a parte il fatto che il tipo di orologio interno è aritmetica.

Nella maggior parte dei casi, siete interessati a intervalli di tempo, quindi mi piacerebbe convertire la differenza di clock ticks a millisecondi. Un unsigned long è grande abbastanza per rappresentare un intervallo di quasi 50 giorni, anche se i suoi 32 bit, quindi dovrebbe essere abbastanza grande per la maggior parte dei casi:

clock_t start;
clock_t end;
unsigned long millis = (end - start) * 1000 / CLOCKS_PER_SEC;

Un modo è quello di utilizzare la funzione gettimeofday. Si può trovare la differenza di utilizzare questa funzione:

unsigned long  diff(struct timeval second, struct timeval first)
{
    struct timeval  lapsed;
    struct timezone tzp;
    unsigned long t;

    if (first.tv_usec > second.tv_usec) {
        second.tv_usec += 1000000;
        second.tv_sec--;
    }

    lapsed.tv_usec = second.tv_usec - first.tv_usec;
    lapsed.tv_sec  = second.tv_sec  - first.tv_sec;
    t = lapsed.tv_sec*1000000 + lapsed.tv_usec;

    printf("%lu,%lu - %lu,%lu = %ld,%ld\n",
           second.tv_sec, second.tv_usec,
           first.tv_sec,  first.tv_usec,
           lapsed.tv_sec, lapsed.tv_usec);

    return t;
}
Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top