Pergunta

Atualmente estou usando um elenco explícito de unsigned long long e usando %llu imprimi-lo, mas desde size_t tem o especificador %z, por que não clock_t tem um?

Não há sequer uma macro para isso. Talvez eu possa supor que em um sistema x64 (OS e CPU) size_t é de 8 bytes de comprimento (e mesmo neste caso, eles têm fornecido %z), mas que sobre clock_t?

Foi útil?

Solução

Não parece haver nenhuma maneira perfeita. A raiz do problema é que clock_t pode ser inteiro ou de vírgula flutuante.

clock_t pode ser um tipo de ponto flutuante

Como Bastien Léonard menciona para POSIX (ir upvote-lo), C99 N1256 projecto 7.23.1 / 3 também diz que:

[clock_t é] tipos aritméticos capazes de representar vezes

e 6.2.5 / 18:

Integer e tipos flutuantes são chamados coletivamente de tipos aritméticos.

e o padrão define tipo aritmética como quer inteiros ou flutuantes tipos de pontos.

Se você dividir por CLOCKS_PER_SEC, uso a longo dupla

O valor de retorno de clock() é implementação definida, ea única maneira de obter significado padrão de fora, é para dividir por CLOCKS_PER_SEC para encontrar o número de segundos:

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

Isso é bom o suficiente, embora não seja perfeito, pelas duas razões seguintes:

  • parece haver nenhum análogo ao intmax_t para tipos de ponto flutuante: Como obter a maior precisão flutuante tipo de dados ponto de implemenation e sua printf especificador? Então, se um tipo de ponto flutuante maior sai amanhã, poderia ser usado e quebrar a sua implementação.

  • Se clock_t é um inteiro, o elenco de flutuador é bem definido para usar o flutuador mais próximo possível. Você pode perder precisão, mas não importa muito em comparação com o valor absoluto, e só iria acontecer por enormes quantidades de tempo, por exemplo, long int em x86 é a bóia 80-bit com 64-bit significativa, que é milhões de anos em segundos.

Go upvote lemonad que disse algo similar.

Se você acha que ele é um inteiro, uso% ju e uintmax_t

Embora unsigned long long é atualmente o maior tipo inteiro padrão possível:

por isso é melhor para distribuir os papéis para o maior tipo inteiro sem sinal possível:

#include <stdint.h>

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

uintmax_t está garantido para ter o tamanho do maior tamanho inteiro possível na máquina.

uintmax_t e sua %ju printf especificador foram introduzidos em c99 e gcc, por exemplo, implementa-las.

Como um bônus, isso resolve uma vez por todas a questão de como confiável printf inteiro tipos (que infelizmente não é o necessariamente o caso para clock_t).

O que poderia dar errado se foi um duplo:

  • se for demasiado grande para caber em um inteiro, um comportamento indefinido
  • muito menor do que 1, vai ser arredondado para 0 e você não vai ver nada

Uma vez que essas conseqüências são muito mais duras do que o inteiro para conversão de float, usando float é provavelmente uma idéia melhor.

Em glibc 2.21 é um inteiro

O manual diz que o uso de double é uma idéia melhor:

sistemas em GNU / Linux e GNU / Hurd, clock_t é equivalente a long int e CLOCKS_PER_SEC é um valor inteiro. Mas em outros sistemas, tanto clock_t ea macro CLOCKS_PER_SEC podem ser tanto inteiros ou de ponto flutuante tipos. Fundição valores de tempo de CPU para o dobro, como no exemplo acima, torna-se de que as operações tais como o trabalho aritmética e imprimindo corretamente e consiste dontly Não importa o que a representação subjacente é.

Em glibc 2.21:

Veja também

Outras dicas

Tanto quanto eu sei, a maneira que você está fazendo é o melhor. Só que clock_t pode ser um tipo real:

time_t e clock_t será inteiro ou tipos flutuante real.

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

É provavelmente porque tiques do relógio não é uma unidade muito bem definido. Você pode convertê-lo em segundos e imprimi-lo como um duplo:

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

Os CLOCKS_PER_SEC expande macro para uma expressão representando o número de tiques do relógio em um segundo.

O padrão C tem para acomodar uma grande variedade de arquiteturas, o que torna impossível fazer quaisquer outras garantias além do fato de que o tipo de relógio interno é aritmética.

Na maioria dos casos, você está interessado em intervalos de tempo, então eu converter a diferença de pulsos de clock para milissegundos. Um unsigned long é grande o suficiente para representar um intervalo de cerca de 50 dias, mesmo se o seu 32 bits, por isso deve ser grande o suficiente para a maioria dos casos:

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

Uma maneira é usando a função gettimeofday. Pode-se encontrar a diferença usando esta função:

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;
}
Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top