неподписанное долгое долгое поведение, странное в C

Я споткнулся через очень странную проблему, управляя программой, собранной для MIPS. Следующий отрывок кода должен получить эпоху времени и сохранить его в точности микросекунды в , неподписанный длинный длинный переменная.

Переменная способна к хранению 8 байтов, с которыми я сверился sizeof (неподписанный длинный длинный) .

Этот код распечатывает странно:

unsigned long long microtime=0;
struct timeval time_camera = { .tv_sec=0, .tv_usec=0 };
gettimeofday(&time_camera,NULL);
microtime = time_camera.tv_sec * 1000000 + time_camera.tv_usec;
printf("Times is now %llu , time since epoch in seconds is: %lu\n", microtime, time_camera.tv_sec);

Это дает мне следующую продукцию:

>> Times is now 484305845 , time since epoch in seconds is: 1357751315

Однако, когда я ломаю вычисление в различные линии, оно работает!:

unsigned long long microtime=0;
struct timeval time_camera = { .tv_sec=0, .tv_usec=0 };
gettimeofday(&time_camera,NULL);
microtime = time_camera.tv_sec;
microtime = microtime * 1000000;
microtime = microtime  + time_camera.tv_usec;
printf("Times is now %llu , time since epoch in seconds is: %lu\n", microtime, time_camera.tv_sec);

Продукция:

Times is now 1357751437422143 , time since epoch in seconds is: 1357751437

Теперь это - просто совпадение, что это работает? например, я испортил память или на самом деле превысил ее где-нибудь? Возможно, это - MIPS compilator? Любая помощь ценится!

1
nl ja de

2 ответы

microtime = time_camera.tv_sec * 1000000 + time_camera.tv_usec;

tv_sec is a smaller Вteger type (time_t, probably Вt or long), so

time_camera.tv_sec * 1000000

переполнение. Используйте суффикс, чтобы дать константе соответствующий тип

time_camera.tv_sec * 1000000ULL

В

microtime = time_camera.tv_sec;
microtime = microtime * 1000000;

the multiplication is performed at unsigned long long, sВce one operand (microtime) already has that type, so the other is converted to that.

9
добавлено

Похож на вас, просто имеют size_t математика, продолжающаяся, прежде чем вы назначите на ваш , неподписанный длинный длинный . попытайтесь поместить ULL после ваших констант.

Другой способ сделать это (неподписанный длинный длинный) 1000000 . Пока у вас есть это на по крайней мере одном из ваших операндов в умножении, вас можно уверить, что результатом будет более высокий тип предшествования. Правила предшествования неявного преобразования типов (в порядке самого высокого к самому низкому):

long double => double => float => unsigned long long => long long => unsigned long => long => unsigned int => int

4
добавлено
Спасибо за регистрацию правил предшествования!
добавлено автор Mazze, источник