Функция типа unsigned int возвращает отрицательное число - PullRequest
2 голосов
/ 01 октября 2011

Ух ты, я думал, что знаю свой C ++, но это странно

Эта функция возвращает беззнаковое целое, поэтому я подумал, что это означает, что я никогда не получу отрицательное число, верное, верно?

Функция определяетсколько часов впереди или позади UTC.Так что для меня я нахожусь в Австралии, Сиднее, поэтому я +10 по Гринвичу, что означает, что я UTC = LocalTime + (-10).Поэтому GetTimeZoneInformation правильно определяет, что я -10.

НО моя функция возвращает беззнаковое целое, поэтому не должна ли она возвращать 10, а не -10?

unsigned int getTimeZoneBias()
{
    TIME_ZONE_INFORMATION tzInfo;
    DWORD res  = GetTimeZoneInformation( &tzInfo );

    if ( res == TIME_ZONE_ID_INVALID )
    {
        return (INT_MAX/2); 
    }

    return (unsigned int(tzInfo.Bias / 60));  // convert from minutes to hours         
}

TCHAR ch[200];
_stprintf( ch, _T("A: %d\n"), getTimeZoneBias()); // this prints out A: -10
debugLog += _T("Bias: ") + tstring(ch) + _T("\r\n");

Ответы [ 4 ]

10 голосов
/ 01 октября 2011

Вы пытаетесь напечатать unsigned int как signed int. Изменить %d на %u

_stprintf( ch, _T("A: %u\n"), getTimeZoneBias());
                       ^

Проблема в том, что целые числа сами по себе не являются положительными или отрицательными для большинства компьютеров . Это в том, как они интерпретируются.

Таким образом, большое целое число может быть неотличимо от малого (абсолютного значения) отрицательного значения.

4 голосов
/ 01 октября 2011

Вот что я думаю:

Значение tzInfo.Bias на самом деле -10. (0xFFFFFFF6) В большинстве систем приведение целого числа со знаком к целому числу без знака того же размера никак не влияет на представление.

Таким образом, функция по-прежнему возвращает 0xFFFFFFF6.

Но когда вы распечатываете, вы печатаете его обратно как целое число со знаком. Так что печатает -10. Если вы напечатаете его как целое число без знака, вы, вероятно, получите 4294967286.

Что вы, вероятно, пытаетесь сделать, это получить абсолютную величину разницы во времени. Итак, вы хотите конвертировать это -10 в 10. В котором вы должны вернуть abs(tzInfo.Bias / 60).

2 голосов
/ 01 октября 2011

Одна ошибка в вашем _T звонке. Должно быть:

_T("A: %u\n")

Функция делает возвращает неотрицательное целое число. Однако, используя неправильный спецификатор printf, вы заставляете его выталкиваться из стека как целое число. Другими словами, биты интерпретируются неправильно. Я считаю, что это также неопределенное поведение.

1 голос
/ 01 октября 2011

Как уже отмечали другие люди, когда вы приводите к unsigned int, вы фактически указываете компилятору использовать шаблон битов в int и использовать его как unsigned int. Если ваш компьютер использует два дополнения , как это делают большинство, то ваш номер будет интерпретироваться как UINT_MAX-10 вместо 10, как вы ожидали. Когда вы используете спецификатор формата %d, компилятор возвращается к использованию того же битового шаблона, что и int вместо unsigned int. Вот почему вы все еще получаете -10.

Если вам нужно абсолютное значение целого числа, вы должны попытаться получить его математически, а не использовать приведение.

...