【发布时间】:2021-11-15 18:47:32
【问题描述】:
我使用sprintf() 填充缓冲区,然后通过 UART 发送此缓冲区。
我已经关注了sprintf 的许多示例和用例,但我的代码似乎不起作用
这是我的代码示例:
#include "stdio.h"
#include "usart.h"
#define Uart husart1
int main(void)
{
uint32_t m = 3;
char c = 'A';
uint32_t o = 1;
char buffer[256];
sprintf(buffer, "AT+,%lu,%c,%lu\r\n", m, c, o);
HAL_UART_Transmit(&Uart, (uint8_t*) buffer, strlen(buffer), 1000);
}
有了这段代码,我的输出是AT+,lu,,lu
你知道出了什么问题吗?
编辑 1:
当我用%d 替换%lu 时,我的编译器说这个错误:
format '%d' expects argument of type 'int', but argument 5 has type 'uint32_t {aka long unsigned int}' [-Wformat=]
所以我有%ld,缓冲区发送就像AT+,ld,,ld
编辑 2:
当我用%u 替换%lu 时,我的编译器说这个错误:
format '%u' expects argument of type 'unsigned int', but argument 3 has type 'uint32_t {aka long unsigned int}' [-Wformat=]
编辑 3:
与#include <stdio.h> 我有同样的错误
编辑 4:关于我想保留 uint32_t 的答案,因为我的 AT 参数可以是 32 位长
编辑 5: 我尝试使用 %d 和 (int16_t) 将类型转换如下:
sprintf(buffer, "AT+,%d,%c,%d\r\n", (int16_t) m, c, (int16_t) o);
这次我的结果是"AT+, ,A, "
为什么我的代码对有符号或无符号整数感到不安?
编辑 6:
使用 inttypes.h,它看起来像这样:
sprintf(buffer, "AT+,%"PRIu32",%c,%"PRIu32"\r\n", m, c, o);
我的输出仍然像 AT+,lu,,lu
【问题讨论】:
-
您使用什么编译器和编译器选项?你在什么系统上运行?具体来说,您使用的是
sprintf的什么实现? -
取决于架构
%lu(特别是“long”的l)对于 32 位 int 可能是错误的。这确实会导致各种麻烦(当 sprintf 实现也从堆栈中读取接下来的 4 个字节时,例如格式字符串的字节)。 -
对@Peter-ReinstateMonica 提到的内容进行简单测试:将
uint32_ts 改为ints 和sprintf(buffer, "AT+,%d,%c,%d\r\n", m, c, o);。我敢打赌,所有AT命令都可以使用ints 创建。 -
正确的(即可移植的)转换是使用 inttypes.h 中有些笨拙的定义,参见 stackoverflow.com/a/3168298/3150802。
-
关于
#include "stdio.h"- 你有修改过的本地stdio.h吗?为什么不<stdio.h>?