值与类型:用于确定变量是否已签名的代码 [英] value vs type: Code to Determine if a Variable Is Signed or Not

查看:30
本文介绍了值与类型:用于确定变量是否已签名的代码的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我在论坛上遇到了这个问题.答案是这样的:

I came across this question in a forum. The answer is something like this:

#define ISUNSIGNED(a) (a >= 0 && ~a >= 0) 

//Alternatively, assuming the argument is to be a type, one answer would use type casts: 

#define ISUNSIGNED(type) ((type)0 - 1 > 0)

关于这个我有几个问题.为什么我们需要检查~a >= 0?第二个解决方案是什么?我不明白这句话:参数是一种类型".更重要的是,作者声明第一个 #define 在 ANSI C 中不起作用(但在 K&R C 中起作用).为什么不呢?

I have a few questions regarding this.Why do we need to check ~a >= 0? What is the second solution all about? I did not understand the statement: "argument is to be a type". More importantly the author states that first #define will not work in ANSI C (but will work in K&R C). Why not?

推荐答案

#define ISUNSIGNED(a) (a >= 0 && ~a >= 0) 

对于正数的有符号值,a >= 0 将为真(显然)而 ~a >= 0 将为假,因为我们已经翻转位,因此现在设置符号位,导致负值.因此整个表达式为假.

For a signed value which is positive, a >= 0 will be true (obviously) and ~a >= 0 will be false since we've flipped the bits so the sign bit is now set, resulting in a negative value. The entire expression is therefore false.

对于负的有符号值,a >= 0 将是假的(显然)并且表达式的其余部分不会被计算;表达式的总体结果为 false.

For a signed value which is negative, a >= 0 will be false (obviously) and the rest of the expression will not be evaluated; the overall result for the expression is false.

对于无符号值,a >= 0总是为真(显然,因为无符号值不能为负).如果我们翻转这些位,则 ~a >= 0 也是如此,因为即使最高有效位(符号位)设置为 1,它仍然被视为正值.

For an unsigned value, a >= 0 will always be true (obviously, since unsigned values can't be negative). If we flip the bits then ~a >= 0 is also true, since even with the most significant bit (the sign bit) set to 1, it's still treated as a positive value.

所以,如果原始值和它的按位逆都是正数,即它是一个无符号值,则表达式返回真.

So, the expression returns true if the original value and its bitwise inverse are both positive, i.e. it's an unsigned value.

#define ISUNSIGNED(type) ((type)0 - 1 > 0)

这将使用类型而不是值来调用:例如,ISUNSIGNED(int)ISUNSIGNED(unsigned int).

This is to be called with a type rather than a value: ISUNSIGNED(int) or ISUNSIGNED(unsigned int), for example.

对于int,代码扩展为

((int)0 - 1 > 0)  

这是错误的,因为 -1 不大于 0.

which is false, since -1 is not greater than 0.

对于unsigned int,代码扩展为

((unsigned int)0 - 1 > 0) 

表达式中的有符号 10 文字被提升为 unsigned 以匹配第一个 0,所以整个表达式被评估为无符号比较.0 - 1 在无符号算术中将产生最大可能的无符号值(所有位设置为 1),该值大于 0,因此结果为真.

The signed 1 and 0 literals in the expression are promoted to unsigned to match the first 0, so the entire expression is evaluated as an unsigned comparison. 0 - 1 in unsigned arithmetic will wrap around resulting in the largest possible unsigned value (all bits set to 1), which is greater than 0, so the result is true.

至于为什么它适用于 K&RC,而不适用于 ANSI C,也许 这篇文章 可以说明一些问题:

As to why it would work with K&R C, but not ANSI C, maybe this article can shed some light:

当一个 unsigned char 或 unsigned short 被加宽时,结果类型为int 如果一个 int 足够大以表示所有的值较小的类型.否则,结果类型为 unsigned int.价值保留规则对大多数人产生最少意外的算术结果表达.

When an unsigned char or unsigned short is widened, the result type is int if an int is large enough to represent all the values of the smaller type. Otherwise, the result type is unsigned int. The value preserving rule produces the least surprise arithmetic result for most expressions.

我猜这意味着当比较 unsigned short0 时,例如,无符号值被转换为 signed int破坏宏的行为.

I guess that means that when comparing an unsigned short to 0, for example, the unsigned value is converted to a signed int which breaks the behaviour of the macro.

您可能可以通过使用 (aa) 来解决这个问题,它根据需要计算为有符号或无符号零,而不是始终有符号的文字 0.

You can probably work around this by having (a-a) which evaluates to either signed or unsigned zero as appropriate, instead of the literal 0 which is always signed.

这篇关于值与类型:用于确定变量是否已签名的代码的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆