C проверка на представление числа со знаком - PullRequest
4 голосов
/ 09 ноября 2011

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

Файл: 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

Файл: a.c

#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 Ответ

5 голосов
/ 09 ноября 2011

Я думаю, вам лучше просто замаскировать кусочки негатива 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 используют одно и то же значение бита знака. Но (а) серьезно? и (b) это работает для типов 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. Это может или не может беспокоить вас ...

...