Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/github/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
在ANSI C中如何确定变量是否无符号_C - Fatal编程技术网

在ANSI 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。 问题是如何确定

我正在学习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。 问题是如何确定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));
}