我有一个关于STM32微控制器的C语言类型转换的问题。现在,我正在尝试编写自己的库来控制微控制器的外围设备。但是我不明白为什么以及什么时候我应该使用像(uint32_t)这样的类型转换。
例如,对于GPIO配置寄存器,我看到了下面的示例:
#define INPUT_ANALOG ((uint32_t) 0x00)
#define INPUT_FLOATING ((uint32_t) 0x01)
#define INPUT_PUP_PDOWN ((uint32_t) 0x02)此信息来自数据表(附在下面的打印屏幕)。这里我不明白为什么要使用类型转换(uint32_t),而不仅仅是0x00或0。
我可以将下一段代码用于相同的目的吗?
typedef enum{
INPUT_ANALOG = 0,
IN_FLOATING,
IN_PULL_UP_DOWN,
}PinConfInput_t;我应该为这段代码做一个类型转换吗?你能给我推荐一些关于定型的学习资料吗?谢谢

发布于 2020-07-04 21:53:44
将类型转换为unsigned int 或后缀u/U在许多上下文中都需要值0x00、0x01和0x02。0x00、0x01和0x02本身都是int类型的常量,并且在int上有一些位摆动的东西是可疑的,例如当位将它们移位到符号位置时!
如果取值0x02 (int)并将其左移到位31:30,就会发生这种情况!所以,
0x02 << 30在整数为32位宽的计算机上具有未定义的行为,而
0x02U << 30 或
((uint32_t)0x02) << 30不会的。
枚举列表的标识符声明为(C11 6.7.2.2p3)
类型为int的
常量,并且可以出现在允许的任何位置。
即,是的,它们也将需要用于这些位移位的强制转换。
请注意,C中的枚举常量的类型不必是枚举本身的类型:
#include <stdio.h>
enum foo {
bar = 42
};
int main(void) {
printf("An enumeration constant is an %s\n",
_Generic(bar,
int: "int",
unsigned int: "unsigned int",
default: "something else"));
printf("On this implementation the enum foo is %s\n",
_Generic((enum foo) 0,
int: "int",
unsigned int: "unsigned int",
default: "something else"));
}在GCC上,这将为枚举常量类型打印int,为enum foo类型打印unsigned int。即常量具有与实际枚举不同的类型。
此外,使用整数范围之外的枚举常量是违反约束的;由于0x80000000在32位系统上不能表示为int,因此它不能用作可移植的枚举常量:
% gcc enumtest.c -std=c11 -pedantic
enumtest.c:5:11: warning: ISO C restricts enumerator values to range of ‘int’
[-Wpedantic]
5 | bar = 0x80000000
| ^~~~~~~~~~最后,正如C标准所说的,枚举的类型由编译器决定,一些编译器可能会使用unsigned char来表示简短的枚举。好吧,你甚至可能需要一个类型转换,因为unsigned char将被提升为signed int,而不是在算术之前的unsigned int。
发布于 2020-07-05 04:35:41
GCC、KEIL和IAR仅应答。
在ARM Cortex编程中有3个最流行的编译器。超过99%的ARM Cottex程序员使用ARM/Keil、IAR和gcc。据统计,大多数STM32程序员使用的是gcc (STM32使用的是gcc作为编译器)。gcc是一个伟大的但不符合标准的C编译器,它有自己的C方言。
gcc:

KEIL

IAR:您需要定义大到不适合带符号类型的枚举。IAR使用足以容纳所有枚举值的任何整数类型(包括unsigned long long)。它会自动选择是使用有符号类型还是无符号类型(例如,使用的最大枚举值将是0x80,它是一个无符号常量-类型将是unsigned char)。
因此,如果您使用这3个编译器中的任何一个编译代码,并且没有任何负值,则使用的类型将是unsigned int或unsigned char,并且不需要强制转换
https://stackoverflow.com/questions/62729686
复制相似问题