我正在学习Peter Van Der Linden的"专家C编程".在A.6章中,写者描述了如何在K&R C中确定变量是否是无符号的.宏如下:
#define ISUNSIGNED(a) (a>=0 && ~a>=0)
Run Code Online (Sandbox Code Playgroud)
这本书很古老,它于1994年首次出版!我之前没有学过K&R C. 问题是如何在ANSI C中确定变量是否是无符号的.
我试图像这样解决问题.由于"0"在ANSI C中是int,并且当与0比较时,除了float,double和long double之外的任何其他数字将通过Integer Upgrade转换为int或unsigned int.所以我想找到unsigned和signed number之间的边.当我将(边缘类型)0与a进行比较时,a的类型将不会改变.宏也是模型如下:
#define ISUNSIGNED(a) (a>=(the edge type)0 && ~a>=(the edge type)0)
Run Code Online (Sandbox Code Playgroud)
我找不到边缘类型,有没有人可以帮我解决问题?我已将"数字"更改为"变量"以获得更准确的表达.
Chr*_*utz 13
签名变量必须将其符号存储一些.通常这是最重要的一个,但它可能是其中任何一个.无符号变量没有符号位; 因此,它可以容纳的最低值是0.这意味着对于无符号变量a
,表达式a >= 0
将始终为true.
所以我们有:
( a >= 0 && ~a >= 0 )
Run Code Online (Sandbox Code Playgroud)
如果a
是无符号的,则第一个为真(必须是),第二个为真(因为无论值~a
是什么,它仍然是无符号值,所以它仍然是>= 0
).如果a
已签名,则表示如果设置了符号位,a >= 0
则为false(并且表达式返回false,表明此变量具有签名类型).如果没有在设置的签位a
,那么当~a
反转所有的位a
,符号位(哪一个它是)有进行设置.这意味着它必须是负数,这意味着~a >= 0
返回false.
这确实依赖于标准整数促销,就像您期望的那样.
unsigned char x = 1; // or whatever
printf("%s\n", ISUNSIGNED(x) ? "TRUE" : "FALSE"); // prints "FALSE"
Run Code Online (Sandbox Code Playgroud)
正如别人指出的那样,unsigned char
被提升到一个int
因为任何价值~a
的一个unsigned char a
可以很容易地适应的范围int
.这可以说是标准整数提升中的失败(或者整数文字的输入失败).
可能存在可以克服此限制的另一个实现ISUNSIGNED
或ISSIGNED
某个地方.在P99宏库有宏的一些令人费解的用途,许多依靠C99的复杂的宏,但不幸的是宏检查表达式是否签署与否(#define SIGNED(expr) ((1 ? -1 : expr) < (1 ? 0 : expr))
)屈从于相同的整数促销.这可能是你能做到的最好的事情(尽管我认为在你想要它的情况下它总比没有好).