作为一个练习,我想写一个宏,它告诉我是否签署了整数变量。这就是我到目前为止所得到的结果,如果我在使用gcc -fsigned-char或-funsigned-char的char变量上尝试这个结果,我会得到结果。
#define ISVARSIGNED(V) (V = -1, (V < 0) ? 1 : 0)
这可移植吗?有没有办法在不破坏变量值的情况下做到这一点?
答案 0 :(得分:5)
#define ISVARSIGNED(V) ((-(V) < 0) != ((V) < 0))
不破坏变量的值。但不适用于0值。
怎么样:
#define ISVARSIGNED(V) (((V)-(V)-1) < 0)
答案 1 :(得分:5)
如果您正在使用GCC,则可以使用typeof
关键字来覆盖该值:
#define ISVARSIGNED(V) ({ typeof (V) _V = -1; _V < 0 ? 1 : 0 })
这会创建一个临时变量_V
,其类型与V
相同。
至于便携性,我不知道。它可以在两个赞美机器上工作(也就是说,你的代码将在任何可能的情况下运行的所有东西),我相信它也适用于一个人的赞美和符号级别的机器。另请注意,如果您使用typeof
,则可能需要将-1
投射到typeof (V)
以使其更安全(即不太可能触发警告)。
答案 2 :(得分:5)
#define ISVARSIGNED(V) ((V)<0 || (-V)<0 || (V-1)<0)
不会改变V的值。第三个测试处理V == 0的情况。
在我的编译器(gcc / cygwin)上,这适用于int
和long
,但不适用于char
或short
。
#define ISVARSIGNED(V) ((V)-1<0 || -(V)-1<0)
也可以完成两项测试。
答案 3 :(得分:1)
这个简单的解决方案没有副作用,包括只引用v一次的好处(这在宏中很重要)。我们使用gcc扩展名“typeof”来获取v的类型,然后将-1转换为此类型:
#define IS_SIGNED_TYPE(v) ((typeof(v))-1 <= 0)
&lt; =而不仅仅是&lt;在某些情况下(启用时)避免编译器警告。
答案 4 :(得分:1)
对所有“使其消极”答案的不同方法:
#define ISVARSIGNED(V) (~(V^V)<0)
这样就不需要为V的不同值设置特殊情况,因为∀V∈ℤ,V ^ V = 0.
答案 5 :(得分:0)
为什么你需要它作为宏?模板非常适合:
template <typename T>
bool is_signed(T) {
static_assert(std::numeric_limits<T>::is_specialized, "Specialize std::numeric_limits<T>");
return std::numeric_limits<T>::is_signed;
}
对于所有基本积分类型,它都是开箱即用的。它在编译时也会在指针上失败,只使用减法和比较的版本可能不会。
编辑:哎呀,问题需要C.但是,模板是很好的方式:P
答案 6 :(得分:-1)
有符号/无符号数学的一个显着特征是当您右移有符号数时,最高有效位被复制。当您移位无符号数时,新位为0.
#define HIGH_BIT(n) ((n) & (1 << sizeof(n) * CHAR_BITS - 1))
#define IS_SIGNED(n) (HIGH_BIT(n) ? HIGH_BIT(n >> 1) != 0 : HIGH_BIT(~n >> 1) != 0
基本上,这个宏使用条件表达式来确定是否设置了数字的高位。如果不是,则宏通过按位否定数字来设置它。我们不能进行算术否定,因为-0 == 0.然后我们向右移1位并测试符号扩展是否发生。
这假定2的补码算法,但这通常是一个安全的假设。