What is the reason for explicit declaration of L or UL for long values

From an example

unsigned long x = 12345678UL 

We always found out that the compiler should see only the β€œlong” in the above example in order to set 4 bytes (in 32 bits) of memory. The question is why we should use L / UL in long constants even after declaring it long.

+19
c constants
Oct 30 '12 at 8:10
source share
4 answers

When the suffix L or UL not used, the compiler uses the first type, which can contain a constant from a list (see details in the C99 standard, section 6.4.4: 5. For a decimal constant, list int , long int , long long int ).

As a result, in most cases there is no need to use a suffix. This does not change the meaning of the program. This does not change the initialization value of your example x for most architectures, although that would be if you chose a number that could not be represented as long long . See also codebauer's answer for an example where part of the U suffix is ​​needed.




There are several circumstances when a programmer may want to explicitly indicate the type of constant. One example is the use of a variational function:

 printf("%lld", 1LL); // correct printf("%lld", 1); // undefined behavior 



A common reason for using a suffix is ​​that the result of the calculation does not overflow. Two examples:

 long x = 10000L * 4096L; unsigned long long y = 1ULL << 36; 

In both examples, without suffixes, the constants would be of type int , and the calculation would be done as int . In each example, this carries the risk of overflow. The use of suffixes means that the calculation will be performed in a larger type instead, which has a sufficient range for the result.

According to Lightness Races in Orbit, the litteral suffix counts to . In the two examples above, simply declaring x as long and y as unsigned long long not enough to prevent overflow when evaluating the expressions assigned to it.




Another example is the comparison x < 12U , where the variable x is of type int . Without the U suffix, the compiler sets the constant 12 to int , and so the comparison is a comparison of signed ints.

 int x = -3; printf("%d\n", x < 12); // prints 1 because it true that -3 < 12 

With the suffix U comparison becomes a comparison of unsigned ints. "Normal arithmetic conversions" means that -3 is converted to a large unsigned int:

 printf("%d\n", x < 12U); // prints 0 because (unsigned int)-3 is large 

In fact, the type of constant can even change the result of an arithmetic calculation, again because of how the "regular arithmetic conversions" work.




Note that for decimal constants, the type list proposed by C99 does not contain an unsigned long long . In C90, the list ended with the largest standardized unsigned integer type at the time (which was unsigned long ). The consequence was that the value of some programs was changed by adding the standard long long type to C99: the same constant that was typed as an unsigned long in C90 can now be entered as a signed long long . I believe that for this reason, it was decided in C99 not to have an unsigned long long in the type list for decimal constants. See this and for an example. p>

+43
30 Oct. '12 at 8:28
source share

Since numeric literals are typical of type int. UL / L tells the compiler that they are not of type int, for example. assuming 32 bit int and 64 bit long

 long i = 0xffff; long j = 0xffffUL; 

Here the values ​​on the right should be converted to signed longs (32 bits β†’ 64 bits)

  • "0xffff", int, is converted to a long extension of the character, resulting in a negative value (0xffffffff)
  • "0xffffUL", unsigned long, will be converted to long, resulting in a positive value (0x0000ffff)
+7
Oct 30 '12 at 8:40
source share

The question is why we should use L / UL in long constants even after declaring it long.

Because it is not "after"; it is "before."

First you have a literal, then it is converted to any type of variable with which you are trying to squeeze it.

+5
Oct. 30
source share

In connection with this post why a u .

The reason for u is the resolution of an integer constant greater than LLONG_MAX in decimal form.

 // Likely to generate a warning. unsigned long long limit63bit = 18446744073709551615`; // 2^64 - 1 // OK unsigned long long limit63bit = 18446744073709551615u`; 
0
Oct 26 '16 at 15:08
source share



All Articles