Здесь вы:
public static class UnixDateTime
{
public static DateTimeOffset FromUnixTimeSeconds(long seconds)
{
if (seconds < -62135596800L || seconds > 253402300799L)
throw new ArgumentOutOfRangeException("seconds", seconds, "");
return new DateTimeOffset(seconds * 10000000L + 621355968000000000L, TimeSpan.Zero);
}
public static DateTimeOffset FromUnixTimeMilliseconds(long milliseconds)
{
if (milliseconds < -62135596800000L || milliseconds > 253402300799999L)
throw new ArgumentOutOfRangeException("milliseconds", milliseconds, "");
return new DateTimeOffset(milliseconds * 10000L + 621355968000000000L, TimeSpan.Zero);
}
public static long ToUnixTimeSeconds(this DateTimeOffset utcDateTime)
{
return utcDateTime.Ticks / 10000000L - 62135596800L;
}
public static long ToUnixTimeMilliseconds(this DateTimeOffset utcDateTime)
{
return utcDateTime.Ticks / 10000L - 62135596800000L;
}
[Test]
public void UnixSeconds()
{
DateTime utcNow = DateTime.UtcNow;
DateTimeOffset utcNowOffset = new DateTimeOffset(utcNow);
long unixTimestampInSeconds = utcNowOffset.ToUnixTimeSeconds();
DateTimeOffset utcNowOffsetTest = UnixDateTime.FromUnixTimeSeconds(unixTimestampInSeconds);
Assert.AreEqual(utcNowOffset.Year, utcNowOffsetTest.Year);
Assert.AreEqual(utcNowOffset.Month, utcNowOffsetTest.Month);
Assert.AreEqual(utcNowOffset.Date, utcNowOffsetTest.Date);
Assert.AreEqual(utcNowOffset.Hour, utcNowOffsetTest.Hour);
Assert.AreEqual(utcNowOffset.Minute, utcNowOffsetTest.Minute);
Assert.AreEqual(utcNowOffset.Second, utcNowOffsetTest.Second);
}
[Test]
public void UnixMilliseconds()
{
DateTime utcNow = DateTime.UtcNow;
DateTimeOffset utcNowOffset = new DateTimeOffset(utcNow);
long unixTimestampInMilliseconds = utcNowOffset.ToUnixTimeMilliseconds();
DateTimeOffset utcNowOffsetTest = UnixDateTime.FromUnixTimeMilliseconds(unixTimestampInMilliseconds);
Assert.AreEqual(utcNowOffset.Year, utcNowOffsetTest.Year);
Assert.AreEqual(utcNowOffset.Month, utcNowOffsetTest.Month);
Assert.AreEqual(utcNowOffset.Date, utcNowOffsetTest.Date);
Assert.AreEqual(utcNowOffset.Hour, utcNowOffsetTest.Hour);
Assert.AreEqual(utcNowOffset.Minute, utcNowOffsetTest.Minute);
Assert.AreEqual(utcNowOffset.Second, utcNowOffsetTest.Second);
Assert.AreEqual(utcNowOffset.Millisecond, utcNowOffsetTest.Millisecond);
}
}
C не разрешает доступ к памяти за пределами конца массива. Однако он позволяет указателю указывать на один элемент за пределами конца массива. Различие важно.
Таким образом, это нормально:
char array[N];
char *p;
char *end;
for (p = array, end = array + N; p < end; ++p)
do_something(p);
(Выполнение * end
было бы ошибкой.)
И это показывает причину, по которой эта функция полезна: указатель, указывающий в (несуществующем) элементе после конца массива полезен для сравнений, например, в циклах.
С технической точки зрения, это все, что позволяет стандарт C. Однако на практике реализация C (компилятор и среда выполнения) не проверяет, получаете ли вы доступ к памяти за пределами конца массива, является ли это одним элементом или несколькими. Необходима проверка границ, что замедлит выполнение программы.
вы можете выйти далеко за пределы 1 после массива например, `
int main()
{
char *string = "string";
int i = 0;
for(i=0; i< 10;i++)
{
printf("%c\n", string[i]);
}
return 0;
}
будет печатать мусор после конца строки слов, независимо от того, что было в памяти до этого.
Часто бывает полезно обозначить "конечную" позицию, которая находится на одну позицию после фактического выделения, поэтому вы можете написать такой код:
char * end = begin + size;
for (char * curr = begin; curr < /* or != */ end ; ++curr) {
/* do something in the loop */
}
Стандарт C явно говорит, что этот элемент является действительный адрес памяти, но разыменовать его по-прежнему не рекомендуется.
Почему у него есть эта гарантия? Допустим, у вас есть машина с 2 ^ 16 байтами памяти, адресами 0000-FFFF, 16-битными указателями. Допустим, вы создали 16-байтовый массив. Может ли память быть выделена в FFF0?
Непрерывно свободно 16 байтов, но:
begin + size == FFF0 + 10 (16 in hex) == 10000
сбрасывается на 0000 из-за размера указателя. Теперь условие цикла:
curr < end == FFF0 < 0000 == false
Вместо итерации по массиву цикл ничего не сделает. Это приведет к поломке большого количества кода, поэтому в стандарте C указано, что распределение недопустимо.