'u'与整数的用法是什么

时间:2018-09-20 19:10:30

标签: c unsigned-integer

此处的代码用于检查输入是否为“ x”。当它是23u时意味着什么,为什么我们不能只写23。

# define IS_X(a) (((unsigned)a | 32) - 97 == 23u)

3 个答案:

答案 0 :(得分:1)

  

'u'与整数一起使用

使用整数常量'u''U'确保常量为unsigned(或unsigned longunsigned long long(大时) )。


  

23u表示什么,

# define IS_X(a) (((unsigned)a | 32) - 97 == 23u)

u使23成为unsigned int 23,而不是signed int 23。这样,将至少以unsigned个数学运算完成比较。

然而,左侧((unsigned)a | 32) - 97的结果是unsigned,因此无论如何比较都将是unsigned@Jonathan Leffler

某些编译器/代码检查器将警告比较unsignedint。通过使用u,双方都是相同的类型,因此不会发出此类警告。

关于编译器是否应警告23是一个单独的问题。

  

为什么我们不能只写23。

代码可能会使用23并冒上述严重警告的危险。


从宏的角度来看,良好的编码习惯是()使用每个参数:

// # define IS_X(a) (((unsigned)a | 32) - 97 == 23u)
//                          v-v
#define IS_X(a) (((unsigned)(a) | 32) - 97 == 23u)

答案 1 :(得分:1)

正如chux和Jonathan Leffler所指出的,((unsigned)a | 32) - 97的结果是无符号的。程序员使用的编译器可能具有非常严格的警告级别,可能抱怨混合了无符号和有符号值的比较。强制后缀为23的第二个操作数u的无符号类型可能已删除此警告。

该宏绝对是可疑的:a应该在扩展中加入括号:

#define IS_X(a) (((unsigned)(a) | 32) - 97 == 23u)

宏可能已经写成((a) == 'x' || (a) == 'X'),但是在大多数情况下a会被评估两次,这是程序员希望避免的。

由于此宏仅适用于ASCII,所以我想知道为什么不使用这种简单得多的替代方法:

#define IS_X(a)  (((a) | 32) == 'x')

答案 2 :(得分:0)

在您给出的示例中,由于通常的算术转换规则,unsigned int强制转换传播,因此每个数字都转换为unsigned。因此,明确地说23是无符号的是没有必要的,而且可以说更难看。

很少需要'u'后缀为整数。我可以考虑使用它有两个原因。

1)如果仅对常量执行多项操作,则有时正是您想要的显式无符号行为。以unsigned int x = 524289 * 4096;为例,假设32位整数,则计算将溢出带符号的版本,这是未定义的行为,但是如果我们如此unsigned int x = 524289u * 4096u;对其进行修改,则它将非常适合unsigned int 。它的行为也总是被定义。我们本可以将值抛给一个,但我认为这更清楚。

2)一个字:警告。每当有符号或无符号整数之间存在比较时,常见的编译器和linter警告都会抱怨,使

unsigned x = 3;
/* Do stuff */
if (x > 2) // Comparison of signed and unsigned integers
{
    /* Do something */
}

引起警告,这可能导致编译失败,具体取决于构建要求的方式。对于带符号整数也可能会执行警告,因此您的短毛猫可能会抱怨:

int roundup16 (int x)
{
    return ((x - 1) | 0xf) + 1;
}

返回x,四舍五入到16的下一个倍数。