以下检查签名号码表示的方法在我的机器上正确检查二进制补码,但是我没有补码或签名幅度机器来检查它。代码是否正常工作,更重要的是,它是否可移植?
文件: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;
}
答案 0 :(得分:5)
我认为你最好只掩盖负面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
使用符号位的相同含义。但(a)认真对待? (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
。这可能会或可能不会打扰你...