C literal suffix U, UL problems

耗尽温柔 提交于 2019-12-13 02:20:38

问题


Could someone explain to me what can happen if I'll forget suffix(postfix) for constants(literals) in ANSI C?

For example I saw for bit shift operations such defines:

#define AAR_INTENSET_NOTRESOLVED_Pos (2UL) /*!< Position of NOTRESOLVED field. */
#define AAR_INTENSET_NOTRESOLVED_Msk (0x1UL << AAR_INTENSET_NOTRESOLVED_Pos) /*!< Bit mask of NOTRESOLVED field. */
#define AAR_INTENSET_NOTRESOLVED_Disabled (0UL) /*!< Interrupt disabled. */
#define AAR_INTENSET_NOTRESOLVED_Enabled (1UL) /*!< Interrupt enabled. */
#define AAR_INTENSET_NOTRESOLVED_Set (1UL) /*!< Enable interrupt on write. */

It's used in 32bit architecture. But it could be ported to 16bit or 8bit. What can happen if postfix UL is not used and I'll use these macros for bit shift operations as it is supposed?

I just assume that e.g. in 8-bit architecture can (1<<30) leads to overflow.

EDIT: I have found nice link: http://dystopiancode.blogspot.cz/2012/08/constant-suffixes-and-prefixes-in-ansi-c.html

But is it safe to use suffixes if the code is supposed to be ported on various architectures?

For instance if suffix U represents unisgned int so for 8bit architecture it's usually 16bit but for 32bit it's 32bit variable, so 0xFFFFAAAAU is ok for 32bit compiler but not for 8bit compiler, right?


回答1:


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."




回答2:


It can break.

It might be better to include the cast in the code itself, i.e.

uint32_t something = (uint32_t) AAR_INTENSET_NOTRESOLVED_Set << 30;

This makes it work even if the #define for the constant is simply an integer.



来源:https://stackoverflow.com/questions/25605777/c-literal-suffix-u-ul-problems

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