用arm-none-eabi-gcc开发STM32也这么长时间了,期初编译过程也遇到过或多或少的问题,
与Keil的ARMCC还是有一些不同的,最近一次为了跑系统节约RAM空间,对以前的代码进行过一些修改,
又发现了一些问题,想着还是记录下来,方便你我他。
写在前面,本文说明的都是使用STM32CubeMX生成的工程,警告等级是生成工程默认的,没有修改:
arm-none-eabi-gcc 编译器的警告
1、加了 const 以后引用的问题
警告如下:
expected 'uint8 * {aka unsigned char *}' but argument is of type 'const uint8 * {aka const unsigned char *}'
问题的起因:
在源程序中本来定义了几个数组:
在其他地方有调用这数组,其实就是使用串口发送数组:
以上程序没有任何问题,是正常的,只是这几个数组在程序运行的时候会占用 ram 空间(属于 .data 段数据),所以为了优化一下,我加上了 const 修饰。
不明白这段话的可以查看我的其他博文:
STM32的内存管理相关(内存架构,内存管理,map文件分析)
这里的目的为的是将数组 保存至 flash 空间。
实际上加了const修饰也表示我把这个数组定义为常量数组,函数调用不允许修改这个数组的值
所以我做了如下修改,在素组前面加了一个 const :
改完以后,其他地方没有变,编译过后,就出现了开头的警告了!
查了一些相关资料得出:
C语言来说: const int和 int 是两种不同的类型 这点一定要弄清楚。
从 const int 转换到 int 就会警告 这时C语言的规定
我们可以通过C语言库函数中的 strstr
来加深一下对 const 是认识。
extern char *strstr(char *str1, const char *str2);
解决办法:
所以为了解决,我去修改了调用这个数组的函数:
但是只是这样修改,又出了一个警告,其实是同样的警告,HAL库函数中的HAL_UART_Transmit
函数参数问题:
最后在这个参数前加了一个强制转换,编译才顺利通过:
最后测试了下,修改后的 Uart3_sendBuffer
在发送不带 const 的数组也不会有警告,所以这个问题暂时这样。
2、missing braces around initializer [-Wmissing-braces]
警告如下:
warning: missing braces around initializer [-Wmissing-braces]
二维数组定义的时候,虽然C语言会自动分配,但是gcc编译器还是会提示少括号的警告(KEIL下不会有):
解决办法:
上图中消除警告的方式,就是加上括号:
3、‘xxx’ may be used uninitialized in this function [-Wmaybe-uninitialized]
警告如下:
warning: 'ReturnCode' may be used uninitialized in this function [-Wmaybe-uninitialized]
在函数中定义了一个枚举类型RETURN_TYPE ReturnCode;
,但是没有赋初始值,会报警告(KEIL下不会有):
其中的 RETURN_TYPE 是枚举类型:
解决办法:
定义的时候给一个初始值:
4、printf 打印类型不匹配警告
警告如下:
warning: format '%x' expects argument of type 'unsigned int', but argument 6 has type 'uint32 {aka long unsigned int}' [-Wformat=]
在使用 printf 打印数据的时候,使用%x ,打印一个 uint32 变量, 出现警告的代码如下:
解决办法:
看来gcc下有严格的数据类型对应,消除警告需要强制转化:
5、void* 类型作为函数变量
错误如下:
warning: dereferencing 'void *' pointer uint32_t gpio_num = (uint32_t)*num;
error: invalid use of void expression uint32_t gpio_num = (uint32_t)*num;
解决办法:
这个问题其实是C语言的使用问题,解决办法如下:
6、enumeration value ‘xxx’ not handled in switch [-Wswitch]
使用switch结构时出现警告"enumeration value ‘xxxxx’ not handled in switch"
解决办法:
在switch结构末添加语句 default:break;