C проверка на представление числа со знаком

Следующий способ проверки подписанных проверок представления чисел для двойок корректно дополняет на моей машине, но у меня нет машин, дополняющих или знаковых величин, чтобы проверить это. Будет ли код работать правильно и, что более важно, переносим ли он?

Файл: platform.h

#ifndef PLATFORM_H
#define PLATFORM_H
#include <limits.h>

static
const union {
    signed char sc;
    unsigned char uc;
} plat_4xvYw = {.sc = -1};

#define IS_TWOS_COMPL (plat_4xvYw.uc == UCHAR_MAX)
#define IS_ONES_COMPL (plat_4xvYw.uc == UCHAR_MAX - 1)
#define IS_SIGNED_MAG (plat_4xvYw.uc == (1U << (CHAR_BIT - 1)) + 1U)

#endif

Файл: ac

#include <inttypes.h>
#include <limits.h>
#include "platform.h"
#include <assert.h>

int
main (void) {

    assert (IS_TWOS_COMPL);
    if (IS_TWOS_COMPL) {

        printf ("twos complement\n");
    } else if (IS_ONES_COMPL) {

        printf ("ones complement\n");
    } else if (IS_SIGNED_MAG) {

        printf ("signed magnitude\n");
    }
    return 0;
}

1 ответ

Решение

Я думаю, что вам лучше просто замаскировать кусочки негатива int:

if ((-1 & 0x1) == 0) {
    // -1 ends in "0" => 1s' complement
} else if ((-1 & 0x2) == 0) {
    // -1 ends in "01" => sign-magnitude
} else {
    // -1 ends in "11" => two's complement
}

Строго говоря, это не говорит вам то же самое, что ваш код, так как нет никакой гарантии, что int а также signed char использовать то же значение знака бита. Но (а) серьезно? и (б) это работает для типов int и больше, для небольших типов это сложнее. unsigned char гарантированно не имеет битов заполнения, но signed char не является. Так что я думаю, что законно иметь (например) CHAR_BIT == 9, UCHAR_MAX = 511, CHAR_MAX = 127, а также signed char имеет 1 бит дополнения. Тогда ваш код может потерпеть неудачу: бит знака в сохраненном значении со знаком не обязательно там, где вы ожидаете, и значение бита заполнения может быть либо 0, либо 1.

Во многих случаях вы можете просто использовать int8_t в программе вместо signed char, Это гарантированно будет дополнением 2, если оно существует, поэтому может избавить вас от заботы о представлении signed char, Если он не существует, программа не будет компилироваться, что является своего рода assertв любом случае. Вы получили бы ложный минус от платформ, которые являются дополнением 2, но не имеют 8-битный символ и, следовательно, не предоставляют int8_t, Это может или не может беспокоить вас...

Другие вопросы по тегам