value vs type:确定变量是否签名的代码

max*_*yne 2 c unsigned signed

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

#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)
Run Code Online (Sandbox Code Playgroud)

我对此有几个问题.为什么我们需要检查~a >= 0?第二个解决方案是什么?我不明白这句话:"论证是一种类型".更重要的是,作者指出,首先#define不适用于ANSI C(但在K&R C中可以使用).为什么不?

Gra*_*and 8

#define ISUNSIGNED(a) (a >= 0 && ~a >= 0) 
Run Code Online (Sandbox Code Playgroud)

对于带正号的有符号值,a >= 0将为真(显然)并且~a >= 0将为假,因为我们已经翻转了位以使符号位现在设置,从而产生负值.因此整个表达式都是错误的.

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

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

因此,如果原始值及其按位反转都是正数,则表达式返回true,即它是无符号值.

#define ISUNSIGNED(type) ((type)0 - 1 > 0)
Run Code Online (Sandbox Code Playgroud)

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

对于int,代码扩展为

((int)0 - 1 > 0)  
Run Code Online (Sandbox Code Playgroud)

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

对于unsigned int,代码扩展为

((unsigned int)0 - 1 > 0) 
Run Code Online (Sandbox Code Playgroud)

表达式中的signed 10literals被提升为unsigned匹配第一个0,因此整个表达式被计算为无符号比较.0 - 1在无符号算术中将循环导致最大可能的无符号值(所有位设置为1),大于0,因此结果为true.

至于为什么它可以与K&R C一起工作,而不是ANSI C,也许这篇文章可以解释一下:

当扩展unsigned char或unsigned short时,如果int足够大以表示较小类型的所有值,则结果类型为int.否则,结果类型为unsigned int.值保留规则为大多数表达式生成最少的意外算术结果.

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

您可以通过根据(a-a)需要评估为有符号或无符号零而不是0始终签名的文字来解决此问题.