Как проверить самый старший бит целого числа со знаком или без знака? - PullRequest
1 голос
/ 04 ноября 2019

Учитывая тип данных clock_t, который гарантированно является целым числом, как вы проверяете значение старшего значащего бита, используя переносимый код C? Другими словами, мне нужно определение этой функции:

bool is_msb_set(clock_t clock);

Но вот поворот: вы не знаете размер clock_t и не подписан он или нет (но предполагается, что он "подписан")является комплиментом для двух).

Моей первой мыслью было сделать следующее:

const clock_t MSB = 1 << ((sizeof(clock_t) * 8) - 1);

bool is_msb_set(clock_t value) {
    return value & MSB;
}

, но определение MSB переполняется, если clock_t является знаковым значением. Может быть, я обдумываю это, но я в тупике.

Ответы [ 3 ]

3 голосов
/ 04 ноября 2019

Просто протестируйте значение напрямую без маски:

bool is_msb_set(clock_t value) {
    if (value < 0) return 1;
    return value >> (sizeof(clock_t) * CHAR_BIT - 1);
}

Если левая сторона оператора >> имеет «тип со знаком и отрицательное значение, результирующее значение определяется реализацией», см. C11 6.5.7p5 .

Поскольку мы assumed "signed" is twos-compliment, я могу просто проверить, если value меньше 0, старший бит всегда будет установлен в единицу. Если оно не отрицательное, оно положительное, и clock_t подписано, то >> правильно определено.

Если clock_t не подписано, то value < 0 всегда вернет 0 и, скорее всего, должнобыть оптимизирован компилятором.

Код не должен компилироваться, если clock_t не является целочисленным типом (например, если это float или double), потому что операнды >>нужно иметь целочисленный тип. Так что это будет работать только для целочисленных типов.

2 голосов
/ 04 ноября 2019

Я думаю, что мы можем сначала проверить, является ли clock_t подписанным или неподписанным, и действовать соответственно.

bool is_msb_set(clock_t value) {
    if ((clock_t)-1 < 0) {
        /* clock_t is signed */
        return value < 0;
    } else {
        /* clock_t is unsigned */
        return ((value << 1) >> 1) ^ value;
    }
}
0 голосов
/ 04 ноября 2019

Что вы можете сделать, это привести его к целому числу, которое гарантированно будет достаточно большим (так, долго?) И , тогда проведите свой тест против 1 << ((sizeof(clock_t) * 8) - 1);.

Я бытакже начните с утверждения, что sizeof(clock_t) <= sizeof(long).

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...