Ull Suffix on a Numeric Literal

ULL suffix on a numeric literal

From the gcc manual:

ISO C99 supports data types for integers that are at least 64 bits wide ( . . . ) . To make an integer constant of type long long int, add the suffix LL to the integer. To make an integer constant of type unsigned long long int, add the suffix ULL to the integer.

These suffixes have also been added to C++ in C++11, and were already supported long long (pun intended) before that as compiler extensions.

why we found ULL in the end of patterns used for memory testing?

In case of your code snippet it is only for self-commenting the code.

The suffux llu is used for explicit specifying that an integer constant has the type unsigned long long.

However when a constant is presented in the hexadecimal notation the suffix can be omitted because the compiler itself determines the type of the constant. That is (The C Standard, 6.4.4.1 Integer constants)

5 The type of an integer constant is the first of the corresponding
list in which its value can be represented.

And for hexadecimal integer constants

int
unsigned int
long int
unsigned long int
long long int
unsigned long long int

what is the reason for explicitly declaring L or UL for long values

When a suffix L or UL is 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).

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 x for 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 U part of the suffix is necessary.


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 int and 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.

As Lightness Races in Orbit puts it, the litteral's suffix comes before the assignment. In the two examples above, simply declaring x as long and y as unsigned long long is not enough to prevent the overflow in the computation of the expressions assigned to them.


Another example is the comparison x < 12U where variable x has type int. Without the U suffix, the compiler types the constant 12 as an int, and the comparison is therefore a comparison of signed ints.

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

With the U suffix, the comparison becomes a comparison of unsigned ints. “Usual arithmetic conversions” mean 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 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 long to C99: the same constant that was typed as unsigned long in C90 could now be typed as a signed long long instead. I believe this is the reason why in C99, it was decided not to have unsigned long long in the list of types for decimal constants.
See this and this blog posts for an example.

C literal suffix U, UL problems

A decimal number like -1,1,2,12345678, etc. without any suffix will get the smallest type it will fit, starting with int, long, long long.

An octal or hex number like 0, 0123, 0x123, 0X123 without any suffix will get the smallest type it will fit, starting with int, unsigned, long, unsigned long, long long, unsigned long long.


The following is a potential problem should AAR_INTENSET_NOTRESOLVED_Pos exceed 31. Note: unsigned long must be at least 32 bits. It would result in 0 ** if unsigned long was 32 bits, but non-zero if longer.

(0x1UL << AAR_INTENSET_NOTRESOLVED_Pos)

The following is a similar potential problem should AAR_INTENSET_NOTRESOLVED_Pos exceed 15. 0x1 is an unsigned, which must only be at least 16 bits. Also if unsigned/int is 16 bits, the minimum, 0x1 will be int. So without explicitly using U, 0x1 could be a problem if AAR_INTENSET_NOTRESOLVED_Pos == 15. [@Matt McNabb]

(0x1 << AAR_INTENSET_NOTRESOLVED_Pos)

Bitwise shift operators

"The integer promotions are performed on each of the operands. The type of the result is that of the promoted left operand. If the value of the right operand is negative or is greater than or equal to the width of the promoted left operand, the behavior is undefined." C11dr §6.5.7 3


Machine width is not the key issue. An 8bit or 16bit machine could use 16, 32, etc. bit size int. Again, 16 bit is the minimum size for a compliant C compiler.


[Edit] **
I should have said " It (shifting more than 31 bits) would result in Undefined behavior, UB, if unsigned long was 32 bits."

What do 0LL or 0x0UL mean?

These are constants in C and C++. The suffix LL means the constant is of type long long, and UL means unsigned long.

In general, each L or l represents a long and each U or u represents an unsigned. So, e.g.

1uLL

means the constant 1 with type unsigned long long.

This also applies to floating point numbers:

1.0f    // of type 'float'
1.0 // of type 'double'
1.0L // of type 'long double'

and strings and characters, but they are prefixes:

 'A'   // of type 'char'
L'A' // of type 'wchar_t'
u'A' // of type 'char16_t' (C++0x only)
U'A' // of type 'char32_t' (C++0x only)

In C and C++ the integer constants are evaluated using their original type, which can cause bugs due to integer overflow:

long long nanosec_wrong = 1000000000 * 600;
// ^ you'll get '-1295421440' since the constants are of type 'int'
// which is usually only 32-bit long, not big enough to hold the result.

long long nanosec_correct = 1000000000LL * 600;
// ^ you'll correctly get '600000000000' with this

int secs = 600;
long long nanosec_2 = 1000000000LL * secs;
// ^ use the '1000000000LL' to ensure the multiplication is done as 'long long's.

In Google Go, all integers are evaluated as big integers (no truncation happens),

    var nanosec_correct int64 = 1000000000 * 600

and there is no "usual arithmetic promotion"

    var b int32 = 600
var a int64 = 1000000000 * b
// ^ cannot use 1000000000 * b (type int32) as type int64 in assignment

so the suffixes are not necessary.

Can we assign a unsigned int varaible, 0xFULL literal

It's just a coincidence that it happens to spell out a word. The ULL suffix means you've got an unsigned long long literal, and 0xF or 0x0F you already know: that's 15, except expressed in hexadecimal.

C++ `long long` variable type

It is a suffix that specifies the type of literal (in this case, integer literals).

You can find out more about this in the C++ standard, specifically in 2.14 - Literals

In your case, the answer lies in the following table (from this very part of the standard) : unsigned long long.

Integer literals suffixes

LLU bad suffix on number

Looking at the standards I have available to me (drafts only, but of reasonably recent versions), both C++ and C define both "ULL" and "LLU" as valid suffixes for an integer literal. This may be a recent change which VS2010 doesn't follow, but I note that VS2012 does the exact same thing (i.e only ULL works).

There is a difference between using a signed and unsigned literal, and that is MSVC's behaviour when you right-shift a signed value. A signed literal will be sign-extended, but an unsigned literal will be padded with zero.

In other words, the following contrived example:

unsigned long long l2 = ~0LL >> 5;
unsigned long long l3 = ~0ULL >> 5;

...will produce two different values under MSVC.

So if your library is expecting defined behaviour by stipulating unsigned values, then converting them to unsigned values will potentially result in undefined behaviour.

In short, I think MSVC is being a bit naughty in only accepting one form of the suffix, but the best fix is to switch where the 'U' appears, and not to remove it entirely.



Related Topics



Leave a reply



Submit