obareey
obareey

Reputation: 309

What is the purpose of "Macros for minimum-width integer constants"

In C99 standard Section 7.18.4.1 "Macros for minimum-width integer constants", some macros defined as [U]INT[N]_C(x) for casting constant integers to least data types where N = 8, 16, 32, 64. Why are these macros defined since I can use L, UL, LL or ULL modifiers instead? For example, when I want to use at least 32 bits unsigned constant integer, I can simply write 42UL instead of UINT32_C(42). Since long data type is at least 32 bits wide it is also portable.

So, what is the purpose of these macros?

Upvotes: 7

Views: 1143

Answers (3)

Petr Skocik
Petr Skocik

Reputation: 60117

The macros essentially possibly add an integer constant suffix such as L, LL, U, UL, o UL to their argument, which basically makes them almost equivalent to the corresponding cast, except that the suffix won't ever downcast.

E.g., UINT32_C(42000000000) (42 billion) on an LLP64 architecture will turn into 42000000000U, which will have type UL subject to the rules explained here. The corresponding cast, on the other hand ((uint32_t)42000000000), would truncate it down to uint32_t (unsigned int on LLP64).

I can't think of a good use case, but I imagine it could be usable in some generic bit-twiddling macros that need at least X bits to work, but don't want to remove any extra bits if the user passes in something bigger.

Upvotes: 0

Oktalist
Oktalist

Reputation: 14714

They use the smallest integer type with a width of at least N, so UINT32_C(42) is only equivalent to 42UL on systems where int is smaller than 32 bits. On systems where int is 32 bits or greater, UINT32_C(42) is equivalent to 42U. You could even imagine a system where a short is 32 bits wide, in which case UINT32_C(42) would be equivalent to (unsigned short)42.

EDIT: @obareey It seems that most, if not all, implementations of the standard library do not comply with this part of the standard, perhaps because it is impossible. [glibc bug 2841] [glibc commit b7398be5]

Upvotes: 3

Jens Gustedt
Jens Gustedt

Reputation: 78963

You'd need them in places where you want to make sure that they don't become too wide

#define myConstant UINT32_C(42)

and later

printf( "%" PRId32 " is %s\n", (hasproperty ? toto : myConstant), "rich");

here, if the constant would be UL the expression might be ulong and the variadic function could put a 64bit value on the stack that would be misinterpreted by printf.

Upvotes: 7

Related Questions