C语言 为长值明确声明 L 或 UL 的原因是什么
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/13134956/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
what is the reason for explicitly declaring L or UL for long values
提问by Shash
From an Example
从一个例子
unsigned long x = 12345678UL
We have always learnt that the compiler needs to see only "long" in the above example to set 4 bytes (in 32 bit) of memory. The question is why is should we use L/UL in long constants even after declaring it to be a long.
我们一直都知道编译器只需要在上面的例子中看到“long”就可以设置 4 个字节(32 位)的内存。问题是为什么即使在将 L/UL 声明为 long 之后,我们还要在 long 常量中使用它。
回答by Pascal Cuoq
When a suffix Lor ULis not used, the compiler uses the first type that can contain the constant from a list (see details in C99 standard, clause 6.4.4:5. For a decimal constant, the list is int, long int, long long int).
当后缀L或UL未使用时,编译器使用可以包含列表中常量的第一种类型(请参阅 C99 标准中的详细信息,条款 6.4.4:5。对于十进制常量,列表为int, long int, long long int)。
As a consequence, most of the times, it is not necessary to use the suffix. It does not change the meaning of the program. It does not change the meaning of your example initialization of xfor most architectures, although it would if you had chosen a number that could not be represented as a long long. See also codebauer's answer for an example where the Upart of the suffix is necessary.
因此,在大多数情况下,没有必要使用后缀。它不会改变程序的含义。x对于大多数架构,它不会改变您的示例初始化的含义,尽管如果您选择了一个不能表示为long long. 有关U需要后缀部分的示例,另请参阅 codebauer 的回答。
There are a couple of circumstances when the programmer may want to set the type of the constant explicitly. One example is when using a variadic function:
当程序员可能想要显式设置常量的类型时,有几种情况。一个例子是使用可变参数函数时:
printf("%lld", 1LL); // correct, because 1LL has type long long
printf("%lld", 1); // undefined behavior, because 1 has type int
A common reason to use a suffix is ensuring that the result of a computation doesn't overflow. Two examples are:
使用后缀的一个常见原因是确保计算结果不会溢出。两个例子是:
long x = 10000L * 4096L;
unsigned long long y = 1ULL << 36;
In both examples, without suffixes, the constants would have type intand the computation would be made as int. In each example this incurs a risk of overflow. Using the suffixes means that the computation will be done in a larger type instead, which has sufficient range for the result.
在这两个示例中,如果没有后缀,常量将具有类型int并且计算将作为int。在每个示例中,这都会导致溢出的风险。使用后缀意味着计算将在更大的类型中完成,这对结果有足够的范围。
As Lightness Races in Orbit puts it, the litteral's suffix comes beforethe assignment. In the two examples above, simply declaring xas longand yas unsigned long longis not enough to prevent the overflow in the computation of the expressions assigned to them.
正如 Lightness Races in Orbit 所说,litteral 的后缀出现在赋值之前。在上面的两个例子中,简单地声明xaslong和yasunsigned long long不足以防止分配给它们的表达式的计算溢出。
Another example is the comparison x < 12Uwhere variable xhas type int. Without the Usuffix, the compiler types the constant 12as an int, and the comparison is therefore a comparison of signed ints.
另一个例子是x < 12U变量x具有类型的比较int。如果没有U后缀,编译器会将常量键入12为 an int,因此比较是有符号整数的比较。
int x = -3;
printf("%d\n", x < 12); // prints 1 because it's true that -3 < 12
With the Usuffix, the comparison becomes a comparison of unsigned ints. “Usual arithmetic conversions” mean that -3 is converted to a large unsigned int:
有了U后缀,比较就变成了无符号整数的比较。“通常的算术转换”意味着 -3 被转换为一个大的无符号整数:
printf("%d\n", x < 12U); // prints 0 because (unsigned int)-3 is large
In fact, the type of a constant may even change the result of an arithmetic computation, again because of the way “usual arithmetic conversions” work.
事实上,常量的类型甚至可能改变算术计算的结果,同样是因为“通常的算术转换”的工作方式。
Note that, for decimal constants, the list of types suggested by C99 does not contain unsigned long long. In C90, the list ended with the largest standardized unsigned integer type at the time (which was unsigned long). A consequence was that the meaning of some programs was changed by adding the standard type long longto C99: the same constant that was typed as unsigned longin C90 could now be typed as a signed long longinstead. I believe this is the reason why in C99, it was decided not to have unsigned long longin the list of types for decimal constants.
See thisand thisblog posts for an example.
请注意,对于十进制常量,C99 建议的类型列表不包含unsigned long long. 在 C90 中,该列表以当时最大的标准化无符号整数类型(即unsigned long)结尾。结果是,通过向long longC99添加标准类型改变了某些程序的含义:与unsigned long在 C90中键入的相同常量现在可以键入为有符号long long。我相信这就是为什么在 C99 中决定不在unsigned long long十进制常量类型列表中的原因。有关示例,请参阅此和此博客文章。
回答by codebauer
Because numerical literals are of typicaly of type int. The UL/L tells the compiler that they are not of type int, e.g. assuming 32bit int and 64bit long
因为数字文字通常是 int 类型。UL/L 告诉编译器它们不是 int 类型,例如假设 32bit int 和 64bit long
long i = 0xffff;
long j = 0xffffUL;
Here the values on the right must be converted to signed longs (32bit -> 64bit)
此处右侧的值必须转换为有符号长整型(32 位 -> 64 位)
- The "0xffff", an int, would converted to a long using sign extension, resulting in a negative value (0xffffffff)
- The "0xffffUL", an unsigned long, would be converted to a long, resulting in a positive value (0x0000ffff)
- “0xffff”,一个 int,将使用符号扩展转换为 long,导致负值 (0xffffffff)
- “0xffffUL”,一个无符号长,将被转换为一个长,产生一个正值(0x0000ffff)
回答by Lightness Races in Orbit
The question is why is should we use L/UL in long constants even after declaring it to be a long.
问题是为什么即使在将 L/UL 声明为 long 之后,我们还要在 long 常量中使用它。
Because it's not "after"; it's "before".
因为它不是“之后”;它是“之前”。
First you have the literal, thenit is converted to whatever the type is of the variable you're trying to squeeze it into.
首先,您拥有文字,然后将其转换为您试图将其压缩到的变量的任何类型。
They are two objects. The type of the target is designated by the unsigned longkeywords, as you've said. The type of the source is designated by this suffix because that's the only way to specify the type of a literal.
它们是两个对象。unsigned long正如您所说,目标的类型由关键字指定。源的类型由此后缀指定,因为这是指定文字类型的唯一方法。
回答by chux - Reinstate Monica
Related to this post is why a u.
与这篇文章相关的是为什么一个u.
A reason for uis to allow an integer constantgreater than LLONG_MAXin decimal form.
一个原因u是允许整数常量大于LLONG_MAX十进制形式。
// Likely to generate a warning.
unsigned long long limit63bit = 18446744073709551615`; // 2^64 - 1
// OK
unsigned long long limit63bit = 18446744073709551615u`;

