Shash
Shash

Reputation: 4260

Why are constants terminated by use of L or UL etc

Why are constants in C terminated by use of L or UL etc. For example unsigned long x = 12345678UL;

My question is what is the significance of this and are there any advantages in doing this.

Upvotes: 1

Views: 498

Answers (4)

Aniket Inge
Aniket Inge

Reputation: 25725

because any number such as 12345 is treated as an integer in C. The problem comes when you try to do bitwise operations on them. Then, it can overflow. This can have serious untracable errors and bugs. To avoid that, when a larger constant number is to be assigned to a (unsigned)long variable, UL and L are used.

UL is to tell the compiler to treat the integer token as an unsigned long rather than int

L is to tell the compiler to treat the integer token as long rather than int.

Upvotes: 4

Christoph
Christoph

Reputation: 169713

The suffix of an integer constant forces a minimum integer type, but the compiler will choose a large one (consistent with some constraints on signedness) if the number cannot be represented in it (see C11 6.4.4.1, in particular the table after §5).

If all you do is use the constant to initialize a variable, you don't need any suffix (except for the edge case of a number that is in range of unsigned long long, but not long long - in that case, any of the unsigned suffixes u, ul or ull as well as octal or hexadecimal representation can be used - decimal integer constants without suffix only promote to signed types).

Suffixes become important if you use the constants in more complex expressions because they will determine the result of it, eg

32u << 30

has type unsigned and will truncate the value, whereas

32ull << 30

won't.

Upvotes: 2

Brendan
Brendan

Reputation: 37222

The reason is that C is very badly designed, and will forcibly convert numbers that are too large into an int for no reason whatsoever, unless the programmer hasn't explicitly told the compiler not to be incredibly stupid via. various "numerical constant suffixes" (like UL).

Note that these "numerical constant suffixes" only really push the problem to larger numbers while also causing additional portability problems. For a simple example, consider uint64_t myNumber = 0xFDECBA9876543210UL; (which will break when compiled on a compiler where long int is only 32-bits).

For another example; consider uint128_t myNumber = 0xFDECBA9876543210FDECBA9876543210ULL; which is broken on virtually all compilers (where long long is 64-bit or smaller), and there is no way to do it correctly (as there simply isn't any "128-bit suffix" that can be used).

Upvotes: -1

David Ranieri
David Ranieri

Reputation: 41046

I saw the question which is commented. But my question is different. I want to know the reason behind doing this.

The reason is overflow:

#include <stdio.h>

int main(void)
{
    unsigned long a = 1U << 32;  // (1U  = unsigned int)
    unsigned long b = 1UL << 32; // (1UL = unsigned long int)

    printf("%lu %lu\n", a, b);
    return 0;
}

On my computer int is 32 bits and long is 64, this is the output:

0 4294967296

This is what happens:

a 000000000000000000000000000000000000001 1U
 ^--------------------------------------- << 32 left shift count >= width of type
b 000000000000000000000000000000000000000000000000000000000000000000000000001 1UL
                                        ^---------------------------------- << 32

Upvotes: 1

Related Questions