什么时候应该在C中使用UINT32_C(),INT32_C(),...宏? [英] When should I use UINT32_C(), INT32_C(),... macros in C?

查看:211
本文介绍了什么时候应该在C中使用UINT32_C(),INT32_C(),...宏?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我在项目中切换到定长整数类型的主要原因是,它们在使用它们时帮助我更清楚地考虑整数大小.通过#include <inttypes.h>包括它们还包括许多其他宏,例如打印宏PRIu32PRIu64,...

I switched to fixed-length integer types in my projects mainly because they help me think about integer sizes more clearly when using them. Including them via #include <inttypes.h> also includes a bunch of other macros like the printing macros PRIu32, PRIu64,...

要将常量值分配给固定长度的变量,我可以使用UINT32_C()INT32_C()之类的宏.每当我分配一个恒定值时,我就开始使用它们.

To assign a constant value to a fixed length variable I can use macros like UINT32_C() and INT32_C(). I started using them whenever I assigned a constant value.

这导致类似于以下代码:

This leads to code similar to this:

uint64_t i;
for (i = UINT64_C(0); i < UINT64_C(10); i++) { ... }

现在我看到了几个无关紧要的例子.一个是stdbool.h包含文件:

Now I saw several examples which did not care about that. One is the stdbool.h include file:

#define bool    _Bool
#define false   0
#define true    1

bool在我的机器上的大小为1个字节,因此它看起来不像int.但是01应该是整数,编译器应将其自动转换为正确的类型.如果我在示例中使用该代码,则代码将更容易阅读:

bool has a size of 1 byte on my machine, so it does not look like an int. But 0 and 1 should be integers which should be turned automatically into the right type by the compiler. If I would use that in my example the code would be much easier to read:

uint64_t i;
for (i = 0; i < 10; i++) { ... }

那么我什么时候应该使用像UINT32_C()这样的固定长度常量宏,什么时候应该将其工作留给编译器(我正在使用GCC)?如果我要用MISRA C编写代码怎么办?

So when should I use the fixed length constant macros like UINT32_C() and when should I leave that work to the compiler(I'm using GCC)? What if I would write code in MISRA C?

推荐答案

作为经验法则,当文字类型很重要时,应使用它们.有两件事要考虑:大小和签名.

As a rule of thumb, you should use them when the type of the literal matters. There are two things to consider: the size and the signedness.

关于尺寸:

int类型由最高32767的C标准值保证.由于无法获得类型小于int的整数文字,因此所有小于32767的值都不需要使用宏.如果需要更大的值,那么文字的类型就开始重要了,最好使用这些宏.

An int type is guaranteed by the C standard values up to 32767. Since you can't get an integer literal with a smaller type than int, all values smaller than 32767 should not need to use the macros. If you need larger values, then the type of the literal starts to matter and it is a good idea to use those macros.

关于签名:

不带后缀的整数文字通常是带符号的类型.这是潜在的危险,因为它可能在隐式类型提升期间导致各种形式的细微错误.例如,(my_uint8_t + 1) << 31会在32位系统上导致未定义的行为错误,而(my_uint8_t + 1u) << 31不会.

Integer literals with no suffix are usually of a signed type. This is potentially dangerous, as it can cause all manner of subtle bugs during implicit type promotion. For example (my_uint8_t + 1) << 31 would cause an undefined behavior bug on a 32 bit system, while (my_uint8_t + 1u) << 31 would not.

这就是为什么MISRA有一条规则规定,如果要使用无符号类型,则所有整数文字都应带有u/U后缀.因此,在上面的示例中,您可以使用my_uint8_t + UINT32_C(1),但也可以使用1u,这也许是最易读的.对于MISRA来说都可以.

This is why MISRA has a rule stating that all integer literals should have an u/U suffix if the intention is to use unsigned types. So in my example above you could use my_uint8_t + UINT32_C(1) but you can as well use 1u, which is perhaps the most readable. Either should be fine for MISRA.

至于为什么stdbool.h将true/false定义为1/0,这是因为标准明确指出了这一点.由于向后兼容的原因,C中的布尔条件仍然使用int类型,而不是像C ++中那样使用bool类型.

As for why stdbool.h defines true/false to be 1/0, it is because the standard explicitly says so. Boolean conditions in C still use int type, and not bool type like in C++, for backwards compatibility reasons.

但是,将布尔条件视为C具有真正的布尔类型被认为是一种好的样式. MISRA-C:2012具有与此概念有关的一整套规则,称为本质上是布尔类型.这样可以在静态分析期间提供更好的类型安全性,并防止各种错误.

It is however considered good style to treat boolean conditions as if C had a true boolean type. MISRA-C:2012 has a whole set of rules regarding this concept, called essentially boolean type. This can give better type safety during static analysis and also prevent various bugs.

这篇关于什么时候应该在C中使用UINT32_C(),INT32_C(),...宏?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆