Я пытаюсь использовать
difftime(time_t end, time_t mktime(start) )
рассчитать разницу между двумя разными временами двумя разными способами. Просто ради любопытства. И я обнаружил, что это приводит к разным результатам, неудачам и успехам. Я не знаю, почему это произошло?
Почему это приводит к различным результатам в двух случаях следующим образом?
// Failure Case 1 when execution, segmentation fault
time_t end;
time(&end);
struct tm * start; // defining a pointer
start->tm_hour = 0;
start->tm_min = 0;
start->tm_sec = 0;
start->tm_year = 114;
start->tm_mon = 6;
start->tm_mday = 29;
double second = difftime(end, mktime(start) ); // where problem come from!
// Success Case 2, with expected result
time_t end;
time(&end);
struct tm start; // defining a non-pointer
start.tm_hour = 0;
start.tm_min = 0;
start.tm_sec = 0;
start.tm_year = 114;
start.tm_mon = 6;
start.tm_mday = 29;
double second = difftime(end, mktime( &start) );
Исходный случай 1 не выделяет память, и оба случая не очищают ВСЕ поля в tm
структура, которая может потребоваться для получения правильного результата (и, безусловно, является «хорошей практикой»).
Чтобы решить Случай 1 в C, лучшее решение состоит в том, чтобы использовать calloc
:
struct tm *start = calloc(1, sizeof(struct tm));
start->tm_year = 114;
start->tm_mon = 6;
start->tm_mday = 29;
а потом, когда вам больше не нужен start
ценность, использование
free(start);
(Обратите внимание, что поскольку структура заполнена нулями, вам больше не нужно вручную устанавливать часы, минуты, секунды)
В C ++ вы бы использовали new
вместо:
tm *start = new tm();
...
// After it is finished.
delete start
Пустая скобка в tm()
делает его «заполненным нулевыми значениями» после выделения фактической памяти.
Вариант «Случай 2» является предпочтительным, поскольку он выделяет start
переменная в стеке.
Случай 1 несколько плох, так как выделение памяти для небольших структур данных (маленький обычно означает что-то меньше, чем около 1 КБ, но это зависит от фактической среды выполнения, часы с 64 КБ ОЗУ могут иметь более строгие требования, чем настольный компьютер с 16 ГБ ОЗУ и мобильный телефон будет где-то посередине, в зависимости от того, что это за телефон). Есть по крайней мере две причины, чтобы избежать «маленьких» распределений памяти:
new
или же calloc
намного сложнее, чем выделение в стеке (на типичных машинах выделение пространства в стеке занимает 1-2 инструкции выше и выше той же функции без переменных вообще, где вызов new
или же {c,m}alloc
может быть полдюжины только для вызова и то же самое снова для delete
или же free
и от нескольких десятков до нескольких тысяч инструкций внутри этих библиотечных функций — сколько времени занимает код, во многом зависит от того, как он реализован, и от того, имеется ли во время выполнения некоторая «доступная память», или требуется вызов в ОС, чтобы «получить еще немного» память «так же). И, конечно же, вам нужно следить за распределением, а не «просачивать» его. [Для этого тоже есть решения на C ++, но я уже написал достаточно в этом ответе, чтобы было трудно следовать]Для случая 2 вы можете использовать:
struct tm start = {};
(И опять же, вам не нужно устанавливать нулевые значения для часа, минуты и секунды)
В C ++ правильно опускать struct
, поскольку struct tm { ... };
объявление в соответствующем заголовочном файле делает имя tm
представлять структуру в любом случае — это относится ко всем struct
а также class
Исключением являются только имена, если одно и то же имя используется по-другому, например, есть функция или переменная с именем tm
в том же контексте — в этом случае компилятор выдаст сообщение об ошибке «не понимаю, что вы подразумеваете под tm
здесь «[точная формулировка зависит от того, какой компилятор используется].
Так как оригинальный вопрос определяет ОБА C и C ++, я попытался объяснить