Я знаю, что size_t без знака и, следовательно, отрицательные значения недопустимы, time_t, насколько мне известно, подписано, поэтому мне разрешено присваивать -1 для size_t. Однако для time_t я не совсем уверен. Если я буду следовать определению через заголовочные файлы, я окажусь здесь:
typedef __time_t time_t;
, тогда здесь:
__STD_TYPE __TIME_T_TYPE __time_t; /* Seconds since the Epoch. */
и наконец
#define __TIME_T_TYPE __SYSCALL_SLONG_TYPE
Я не слишком уверен, что __SYSCALL_SLONG_TYPE есть, но я думаю, что это подписанный долго. К сожалению, даже после этой трассировки, я могу только надеяться, что другие платформы C ++ 11 имеют такую же реализацию. Я все еще не уверен, что это будет законно и четко определено для всех них:
size_t foo = -1;
Конечно, имеет смысл сделать time_t подписанным, так как можно иметь отрицательные смещения времени, например, для моделирования часовых поясов. Но, с другой стороны, имеет смысл оставить его без знака, потому что после 1970 года нужно считать много секунд. Так что здравый смысл идет в обе стороны 🙂 Поиск в time_t вернул следующее:
«По историческим причинам оно обычно реализуется как интегральное значение, представляющее количество секунд, прошедших с 00:00 часов, 1 января 1970 года по Гринвичу (т.е. временная метка Unix). Хотя библиотеки могут реализовывать этот тип с использованием альтернативных представлений времени».
Источник: http://www.cplusplus.com/reference/ctime/time_t/
и на той же странице: «Переносимые программы не должны напрямую использовать значения этого типа, но всегда полагаются на вызовы элементов стандартной библиотеки для перевода их в переносимые типы».
Так что time_t совсем не определено во всех системах, однако time () возвращает time_t: так что я бы не стал первым экспортировать его в интерфейс. Какой другой тип я должен использовать?
Я спрашиваю по этим двум причинам:
Вопрос: Поскольку time_t не является четко определенным представлением времени на всех платформах, какой тип данных, который является (1) быстрым и (2) сопоставимым, я могу использовать, который является переносимым?
Например, относительно порядка time_t:
#include <iostream>
#include <ctime>
#include <cstring>
int main() {
struct tm tm_a, tm_b;
memset(&tm_a, 0, sizeof(struct tm));
memset(&tm_b, 0, sizeof(struct tm));
if(strptime("2014-01-01 12:00:00", "%Y-%m-%d %H:%M:%s", &tm_a) && strptime("2014-01-01 11:59:59", "%Y-%m-%d %H:%M:%s", &tm_b)) {
if(mktime(&tm_a) > mktime(&tm_b)) std::cout << "time_t ordering OK." << std::endl;
else std::cout << "time_t ordering tainted" << std::endl;
} else std::cout << "failed to parse time" << std::endl;
return 0;
}
Будет время незапятнанный на всех платформах?
(time_t)(-1)
уже означает «это не действительное время», независимо от того, что time_t
на самом деле Стандартная функция mktime
возвращает это значение при ошибке, вы тоже можете.
Стандарты C и C ++ ничего не говорят о кодировании времени в time_t
, Стандартная функция difftime
вычисляет разницу во времени в секундах, как double
между двумя временами представлен как time_t
и это единственный благословенный способ сделать заказ time_t
ценности в хронологическом порядке. Тем не менее, стандарт POSIX указывает, что time_t
время в секундах, поэтому в системе POSIX все в порядке time_t
непосредственно с <
,
Обратите внимание, что и C, и POSIX позволяют time_t
быть любым арифметическим типом (не просто целым).
Если вам нужно представление времени, которое гарантированно переносимо между различными платформами, вам нужно использовать или создать библиотеку, которая позаботится о различиях между платформами, которые вы используете.
Например Boost.Date_Time, там вы можете выбрать любое представление, которое оно поддерживает. Вы даже можете использовать секунды, прошедшие с эпохи способом, который не зависит от платформы (на всех платформах, поддерживаемых boost).
Я стал зависимым от optional
(через повышение, или сверните свое собственное основанное на C ++ 1y tr рабочий документ).
optional<foo>
это либо foo
или nullopt
, Вы получаете доступ к foo
через разграничение, но данные хранятся в optional
через союз. Моя ленивая реализация использует указатель для foo
или нет «, поскольку это делает отладку тривиальной.
Он передает сообщение об ошибке лучше, чем значения флага, и заменяет набор маркировок на основе указателей в коде, который я пишу.