#c #macos #time #x86-64 #ctime
#c #macos #время #x86-64 #ctime
Вопрос:
Если пользовательский тип time_t
определен как __darwin_time_t
, который сам по себе определяется как long
в macOS X, почему выводится следующий код 8 Time is (null)
? Может быть, это что-то глупое, но я действительно не могу этого понять.
#include <stdio.h>
#include <time.h>
int main(void)
{
time_t time = 0x7FFFFFFFFFFFFFFF;
printf("%lun"
"Time is %sn", sizeof(time_t), ctime(amp;time));
return 0;
}
Комментарии:
1. Я имел в виду
__darwin_time_t
, не__darwin_time
, извините.
Ответ №1:
Время 0x7ffffffffffffffff, по-видимому, приходится примерно на 292 471 210 647 год н.э., что, несомненно, приводит к тому, что ctime
количество символов превышает 26, гарантированное C99, поэтому оно возвращает NULL, а не переполняет его буфер. В общем, старайтесь избегать любых дат, которые происходят после того, как морлоки вступят в войну с элоями.
Комментарии:
1. Ну, идея заключалась в том, чтобы определить, когда будет
time_t
обтекание be. 0x7FFFFFFF по времени Unix произойдет в 2038 году, поэтому, я думаю, нам нужен новый стандарт, прежде чем межпланетные войны начнут часто происходить в нашей галактике.2. Попробуйте вместо этого strftime. Или просто проверьте значение tm_year для localtime или gmt.
Ответ №2:
Работая над книгой «Экспертное программирование на C», я столкнулся с той же проблемой в Lion 10.7.3 — с t=0xf0c00000000000
, ctime(amp;t)
выдает Wed Mar 1 21:07:12 214739252
и с t=0xf0d00000000000, ctime(amp;t)
возвращает нулевой указатель (0x0). Таким образом, похоже, что это не обтекание для t, а некоторый тест внутри ctime(amp;t)
, который возвращает нулевой указатель, если t слишком велико.
Комментарии:
1. Просто сделал то же самое. Смешное.
Ответ №3:
Из реализации glibc мы читаем:
Мы ограничиваем размер года, который может быть напечатан. При использовании используемого спецификатора формата %d добавление 1900 приведет к переполнению числа, и будет напечатан отрицательный результат. Для некоторых архитектур мы теоретически могли бы использовать %ld или еще больший целочисленный формат, но это означало бы, что для вывода требуется больше места. Это не было бы проблемой, если бы интерфейс ‘asctime_r’ был определен разумно и был бы передан размер буфера.
Запустите приведенную ниже программу, чтобы найти точное ограничение на вашем компьютере.
#include <limits.h>
#include <stdio.h>
#include <time.h>
/**
* Find the largest time_t for which ctime returns a non-NULL value
* using a bsearch between 0 and LONG_MAX.
**/
static time_t ctime_max() {
time_t start = 0, end = LONG_MAX, mid;
while (start < end) {
mid = start (end - start) / 2;
if (ctime(amp;mid)) {
/* this mid is ctime-able; try higher */
start = mid 1;
} else {
/* this mid is not ctime-able; try lower */
end = mid;
}
}
/* mid is now the lowest number that's too high; subtract one */
return mid - 1;
}
int main() {
time_t t = ctime_max();
printf("%s", ctime(amp;t));
return 0;
}
Для меня это выходит за Tue Dec 31 23:59:59 2147483647
, что происходит за секунду до того, как year переполняет четыре подписанных байта.
Комментарии:
1. Прошло несколько лет с тех пор, как вы опубликовали этот ответ, но это было полезно! Спасибо, что также связали реализацию glibc. Приветствия 🙂