ctime возвращает null

#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. Приветствия 🙂