首页 > 解决方案 > 两个无符号长表示之间的区别

问题描述

在常量上使用文字后缀有什么区别:

#define MY_LONG 0x1UL

并铸造一个常数:

#define MY_LONG (unsigned long)0x1

什么时候选择前者,什么时候选择后者?

标签: c

解决方案


在常量上使用文字后缀:...和强制转换常量:之间有什么区别?

  1. 这取决于使用情况。

让我们尝试使用 2 个定义作为预处理器控制。预处理器数学不理解各种类型的宽度。作为令牌处理的一部分:

出于此令牌转换和评估的目的,所有有符号整数类型和所有无符号整数类型的行为就好像它们分别具有与类型intmax_tuintmax_t... C11dr §6.10.1 4相同的表示形式

#define MY_LONG1  0x123456789UL
#define MY_LONG2  (unsigned long)0x123456789

int main(void) {
#if MY_LONG1 == 0x123456789u
  puts("MY_LONG1 == 0x123456789u");
#endif
#if MY_LONG2 == 0x123456789u
  puts("MY_LONG2 == 0x123456789u");
#endif
}

#if MY_LONG2 == 0x123456789u导致编译器错误

error: missing binary operator before token "long"
 #define MY_LONG2  (unsigned long)0x123456789

注意:L预处理没有任何作用。
注意:U确实有预处理的目的。

  1. 否则,它取决于常量的值。

值为 1 时,没有区别。

然而,如果该值超过ULONG_MAX,(例如:32 位),则以下为unsigned long long. U保险一些无符号类型,L保险至少 long

#define MY_LONG  0x123456789UL

强制转换可以更改值。在下面的这种情况下,值变为 0x23456789 并键入unsigned long

#define MY_LONG  (unsigned long)0x123456789

什么时候选择前者,什么时候选择后者?

L轻推类型为至少,强制转换long强制类型long

在[-2147483647 ... 2147483647]的最小范围内使用LwhenMY_LONG应该是至少long或值很小long

如果宏可以与预处理一起使用,请不要使用强制转换。

否则使用(long)强制转换来强制执行long. IMO,这很少是目标。一个例外是常量必须unsigned long与它的值无关。

// Works well if unsigned long is 64-bit or less
#define MY_ULONG_EVERY_OTHER_BIT  ((unsigned long) 0xAAAAAAAAAAAAAAAAu)

注意:一般来说,我避免使用Lin 常量,让实现来确定类型。

下面将是适合的最窄类型unsigned, unsigned long , unsigned long long。附加 anL 将适合最窄的 unsigned long, unsigned long long.

#define MY_BIGU  0x123456789u

OP的定义存在一个微妙的问题。

#define MY_LONG  (unsigned long)0x1

它应该是下面的,以确保紧密结合。

#define MY_LONG  ((unsigned long)0x1)

只有少数运算符具有更高的优先级,可能会弄乱代码。病态的例如:MY_LONG[a]会是(unsigned long)(0x1[a])和不是,但除非评估问题的可能性为零,否则((unsigned long)0x1)[a]用 a 包围宏仍然是一种很好的做法。()


推荐阅读