Initializing objects with macros for integer constants

隐身守侯 提交于 2019-12-10 20:56:57

问题


http://www.open-std.org/jtc1/sc22/wg14/www/docs/n1570.pdf 7.20.4 introduces Macro integer constants with:

1 The following function-like macros expand to integer constants suitable for initializing objects that have integer types corresponding to types defined in <stdint.h>. Each macro name corresponds to a similar type name in 7.20.1.2 or 7.20.1.5.

I don't quite understand this paragraph. The macros basically slap the appropriate suffix onto an unsuffixed number as in:

UINT64_C(0x123) => 0x123ULL

But if I wanted to initializes an uint64_t, I would just do:

uint64_t x = 0x123; 

and I wouldn't bother with the suffix at all.

Why would I need these macros in initializations?


回答1:


this UINT64_C(0x123) macro creates an immediate unsigned long long number so it can be used in variable argument functions for instance or intermediate computations without the need for casting into the uint64_t type, where it is important that this particular data type is used.

Example:

printf("%llu\n",UINT64_C(0x123));

is correct

printf("%llu\n",0x123);

is incorrect and is UB because data size isn't correct, and printf cannot know that.

when you do uint64_t x = 0x123;, there's an assignment and an implicit cast, so no need to do this (and printf("%llu\n",x); is correct)

Another usage is in intermediate computations, as illustrated below:

uint32_t a = 0xFFFFFFFF;
uint64_t x = a + UINT64_C(0xFFFFFFFF);

won't overflow whereas

x = a + 0xFFFFFFFF;

will overflow because intermediate result is stored in a uint32_t

As a conclusion, the main functional difference between UINT64_C(SOME_CONSTANT) and (uint64_t)SOME_CONSTANT is that if the value overflows, you'll get a warning in the first case for sure, and a "conversion" in the other case (and maybe a warning but that depends on the compiler).




回答2:


With u64 you tell that you want 64-bit integer. Some platforms provide it by defining unsigned long long, others by unsigned long. If your values are to interoperate with functions that need this info (e.g. printf and pals), you should deal with this indirection in order to have flexible code. In your example (uint64_t ex = 0x123;) type has this information, no need to explicitly call the macro. But I assume you need all the 64-bit, if it exceeds int values, you should have the UL / ULL postfices. Example:

unsigned ex = 0x100000000U;
// warning: large integer implicitly truncated to unsigned type [-Woverflow]


来源:https://stackoverflow.com/questions/40406394/initializing-objects-with-macros-for-integer-constants

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!