两个无符号长表示之间的区别

时间:2018-09-26 07:27:54

标签: c

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

#define MY_LONG 0x1UL

并投射一个常量:

#define MY_LONG (unsigned long)0x1

您何时选择前者,何时选择后者?

5 个答案:

答案 0 :(得分:8)

  

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

  1. 这取决于用途。

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

  

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

#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产生compiler error

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

请注意:L对预处理没有任何作用。
注意:U确实可以进行预处理。

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

值为1,没有区别。

但是,如果值超过ULONG_MAX(例如32位),则下面的内容为unsigned long longU确保某些 unsigned 类型,L确保至少 long

#define MY_LONG  0x123456789UL

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

#define MY_LONG  (unsigned long)0x123456789

  

您何时选择前者,何时选择后者?

L将类型微调为至少long,强制类型转换为long

L最小范围内,当MY_LONG应该至少为long或值很小时,请使用long。 2147483647 ... 2147483647]

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

否则,使用强制转换(long)强制执行long。海事组织,这很少是目标。如果常量无论其值如何都必须为unsigned long,则为例外。

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

注意:通常,我避免在常量中使用L,而让实现确定类型。

以下内容将是unsigned, unsigned long , unsigned long long中最窄的类型。附加L将适合最窄的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],但是仍然是将宏用()括起来的良好实践,除非评估问题的机会为零。

答案 1 :(得分:5)

没有实际差异,它们是100%等效的。

唯一的形式差异是UL是整数常量的一部分,而强制转换可以放在任何表达式的前面,包括运行时评估的表达式。

UL的主要原因是在重要的地方强制使用整数常量的类型。它通常比强制转换更具可读性。示例:1UL << n(unsigned long)1 << n

另一方面,Cast具有更广泛的用途,因为它们不仅可以用于在编译时强制类型,还可以在运行时触发类型转换。

答案 2 :(得分:3)

绝对没有区别。两者都是具有相同值和类型的可编译时评估的常量表达式,尽管您明智的做法是将第二个版本写为((unsigned long)0x1)

我个人会选择第一个,因为它更清晰;至少在我看来,强制类型转换是运行时运算符,而不是编译时运算符。

答案 3 :(得分:1)

两者之间几乎没有什么区别:它们都是常数表达式,其值为1,类型为unsigned long

一个显着的区别是您可以将0x1UL用作预处理程序测试表达式的一部分,但不能使用(unsigned long)1

#include <stdio.h>
#if 0x1UL
int main() {
    return 0;
}
#else
#error 0x1UL should be true
#endif

答案 4 :(得分:0)

从技术上讲,有一种方法可以在它们之间进行区分,但是您确实必须非常努力:

char a [10];
printf( "size is %zu\n", sizeof(MY_LONG [a]) );

在上面的示例中,文字(0x1UL)版本将使数组以unsigned long文字作为索引,并产生1,因为它是sizeof(char)。强制转换版本将使数组以int文字作为索引,然后将生成的char强制转换为unsigned long,然后将其传递给sizeof()sizeof(unsigned long)通常是8

这是因为索引运算符[]的排名高于转换运算符()