在ANSI C中如何确定变量是否无符号
我正在学习Peter Van Der Linden的“C编程专家”。在第A.6章中,作者描述了如何确定K&R C中的变量是否无符号。宏如下所示:在ANSI C中如何确定变量是否无符号,c,C,我正在学习Peter Van Der Linden的“C编程专家”。在第A.6章中,作者描述了如何确定K&R C中的变量是否无符号。宏如下所示: #define ISUNSIGNED(a) (a>=0 && ~a>=0) #define ISUNSIGNED(a) (a>=(the edge type)0 && ~a>=(the edge type)0) 这本书很老了,它第一次出版于1994年!我以前没有学过K&R C。 问题是如何确定
#define ISUNSIGNED(a) (a>=0 && ~a>=0)
#define ISUNSIGNED(a) (a>=(the edge type)0 && ~a>=(the edge type)0)
这本书很老了,它第一次出版于1994年!我以前没有学过K&R C。 问题是如何确定ANSIC中的变量是否无符号 我已经试着这样解决这个问题了。由于“0”在ANSI C中是int,以及除float之外的任何其他数字,所以当与0比较时,double和long double将通过整数升级转换为int或无符号int。所以我想在无符号数和有符号数之间找到一条边。当我将(边缘类型)0与a进行比较时,a的类型不会更改。模型的宏代码如下所示:
#define ISUNSIGNED(a) (a>=0 && ~a>=0)
#define ISUNSIGNED(a) (a>=(the edge type)0 && ~a>=(the edge type)0)
我找不到边缘类型,有人能帮我解决问题吗?
为了更准确地表达,我把“数字”改为“变量”
#define ISUNSIGNED(type) (((type)-1) >= 0)
或
你不能
如果设置了MSB,则有符号的long/int/short/char为负。
如果设置了MSB,则无符号long/int/short/char不是负数。
以表格形式:
MSB=0 MSB=1
unsigned + +
signed + -
因此,答案是:符号是一种解释。相同数量(字节序列)可以解释为有符号或无符号;您无法通过检查数字的值/内容来决定数字是否已签名。这就是静态类型的作用
注意:在注释中提到,C可能不要求MSB作为有符号整数类型的“符号”。然而,这几乎总是正确的
注2:问题的原始表述是关于确定数字的有符号性,而不是变量的有符号性(因此我的答案是关于C中的解释和静态键入)这是如何工作的
有符号变量必须将其符号存储在某个位中。通常这是最重要的一个,但也可能是其中的任何一个。无符号变量没有符号位;因此,它所能保持的最低值为0。这意味着对于无符号变量a
,表达式a>=0
将始终为真
因此,我们:
( a >= 0 && ~a >= 0 )
如果a
是无符号的,则第一个值为真(必须为真),第二个值为真(因为无论~a
是什么值,它仍然是无符号值,因此它仍然是=0
)。如果a
是有符号的,这意味着如果设置了符号位,a>=0
为false(表达式返回false,说明此变量具有有符号类型)。如果符号位未在a
中设置,则当~a
反转a
中的所有位时,必须设置符号位(无论是哪一位)。这意味着它必须是一个负数,这意味着~a>=0
返回false
这确实依赖于标准的整数促销,使其像您期望的那样工作
它怎么不起作用
正如其他人指出的,无符号字符
被提升为int
,因为无符号字符a
的~a
的任何值都可以很容易地适应int
的范围。这可以说是标准整数提升中的一个失败(或者整型文字的键入失败)
可能有另一个
ISUNSIGNED
或ISSIGNED
的实现可以克服此限制。宏有一些令人费解的用法,许多宏依赖于C99的可变宏,但不幸的是,用于检查表达式是否有符号的宏(#define signed(expr)((1-1:expr)<(1-0:expr))
)屈从于相同的整数提升。这可能是你能做的最好的了(尽管我认为在你想要的情况下这比什么都不做要好)。\define ISUNSIGNED(a)(a>=0&&((a=~a)>=0?(a=~a,1):(a=~a,0))
对于任何提出这个问题但不限于C89的人(从技术上讲,C11也是ANSI C,因为ANSI已经批准了它):
#包括
#包括
#定义ISSIGNED(x)\通用((x)\
未签名字符:0\
未签名的短消息:0\
无符号整数:0\
无符号长:0\
无符号长:0\
签名字符:1\
署名:1,\
签名:1\
签名:1\
签署长龙:1,\
字符:(字符最小值<0)\
)
int main()
{
字符x;
printf(“%d\n”,ISSIGNED(x));
}
您必须确定是否设置了有符号位,这就是想法。为什么需要这样的宏?我看不出它有什么用处。(我很好奇)一个数字不用,它可以是正的,也可以是负的。另一方面,类型可以是有符号的,也可以是无符号的(我想,这就是你的问题所在)。无论如何,该代码将不适用于无符号字符
,因为~a
将转换为int
@Mat-它是一个帮助宏。它允许您测试(在另一个更复杂的宏中)给定的参数是有符号类型还是无符号类型,这可能非常重要。它促进了C预处理器的泛型编程。“这本书很老了,它是1994年第一次出版的!”该死!现在我很沮丧…MSB指示+/-可能假设为“2的互补机器架构”。C不是硬连线到这种类型的有符号数字表示。另一方面,我不知道有哪台现代计算机不是2的补充。但我敢打赌,有人可以引用一个关于一些现有大型机仍然存在的好故事……学究式的我认为C标准不能保证符号位是MSB(尽管在实践中可能总是如此)。参考:。那么我猜我的答案仍然成立,也就是说,“你不能(更不用说便携)”我在中发现了一些信息,我认为你错了:内存中的一些字节,是的,符号是一种解释。如果向您传递了一个指向这些字节的void*
,您将无法确定它的写入类型。然而,在C中,每个值都有一个类型
#include <stdio.h>
#include <limits.h>
#define ISSIGNED(x) _Generic((x), \
unsigned char: 0, \
unsigned short: 0, \
unsigned int: 0, \
unsigned long: 0, \
unsigned long long: 0, \
signed char: 1, \
signed short: 1, \
signed int: 1, \
signed long: 1, \
signed long long: 1, \
char: (CHAR_MIN < 0) \
)
int main()
{
char x;
printf("%d\n", ISSIGNED(x));
}