STM32搭载RT-Thread系统时的rt_sprintf函数和stdio.h的sprintf函数的区别

1.问题来源

在工作中,使用STM32搭载RT-Thread操作系统,使用的字符串打印函数一般使用操作系统带的rt_sprintf函数,在使用过程中,将一个浮点数和字符串打印到字符型的数组中时,这个运行的线程就崩了,经过同事解说,了解到rt_sprintf和sprintf有区别,rt_sprintf函数更换成了sprintf后,问题立刻解决,在度娘搜索后没有看到这个问题的说明,在此深入探究两个函数的区别

2.问题探究

(1).stdio.h中的sprintf函数

函数代码

#pragma __printf_args
extern _ARMABI int sprintf(char * __restrict /*s*/, const char * __restrict /*format*/, ...) __attribute__((__nonnull__(1,2)));
   /*
    * is equivalent to fprintf, except that the argument s specifies an array
    * into which the generated output is to be written, rather than to a
    * stream. A null character is written at the end of the characters written;
    * it is not counted as part of the returned sum.
    * Returns: the number of characters written to the array, not counting the
    *          terminating null character.
    */
#pragma __printf_args
extern _ARMABI int _sprintf(char * __restrict /*s*/, const char * __restrict /*format*/, ...) __attribute__((__nonnull__(1,2)));
   /*
    * is equivalent to sprintf, but does not support floating-point formats.
    * You can use instead of sprintf to improve code size.
    * Returns: as sprintf.
    */

(2).RT_Thread操作系统中的rt_sprintf函数

函数代码

/**
 * This function will fill a formatted string to buffer
 *
 * @param  buf the buffer to save formatted string.
 *
 * @param  format is the format parameters.
 *
 * @return The number of characters actually written to buffer.
 */
int rt_sprintf(char *buf, const char *format, ...)
{
    rt_int32_t n;
    va_list arg_ptr;

    va_start(arg_ptr, format);
    n = rt_vsprintf(buf, format, arg_ptr);
    va_end(arg_ptr);

    return n;
}
RTM_EXPORT(rt_sprintf);

(3).问题解决说明

后面看了源码才知道是rt_sprintf无法打印浮点数,具体的现象可以看一下这个,

https://blog.csdn.net/plokm789456/article/details/107087502/

解决方法1

将搭载RT-Thread操作系统的工程中要使用到的“打印”相关函数更换成C语言库stdio.h的函数,例如:rt_sprintf更换成sprintf,在工程文件中添加stdio.h头文件。这是在上层应用程序中解决问题。

解决方法2

将搭载RT-Thread操作系统工程的“打印”函数源码n = rt_vsprintf(buf, format, arg_ptr)中的rt_删了就可以了。例如:将rt_sprintf函数中的rt_删了,

/**
 * This function will fill a formatted string to buffer
 *
 * @param  buf the buffer to save formatted string.
 *
 * @param  format is the format parameters.
 *
 * @return The number of characters actually written to buffer.
 */
int rt_sprintf(char *buf, const char *format, ...)
{
    rt_int32_t n;
    va_list arg_ptr;

    va_start(arg_ptr, format);
    n = vsprintf(buf, format, arg_ptr);
    va_end(arg_ptr);

    return n;
}
RTM_EXPORT(rt_sprintf);

这样源码中的关键函数使用的是C语言库stdio的函数,就没什么问题了。

(4).举一反三

/**
 * This function will print a formatted string on system console.
 *
 * @param fmt is the format parameters.
 *
 * @return The number of characters actually written to buffer.
 */
RT_WEAK int rt_kprintf(const char *fmt, ...)
{
    va_list args;
    rt_size_t length;
    static char rt_log_buf[RT_CONSOLEBUF_SIZE];

    va_start(args, fmt);
    /* the return value of vsnprintf is the number of bytes that would be
     * written to buffer had if the size of the buffer been sufficiently
     * large excluding the terminating null byte. If the output string
     * would be larger than the rt_log_buf, we have to adjust the output
     * length. */
    length = rt_vsnprintf(rt_log_buf, sizeof(rt_log_buf) - 1, fmt, args);
    if (length > RT_CONSOLEBUF_SIZE - 1)
        length = RT_CONSOLEBUF_SIZE - 1;
#ifdef RT_USING_DEVICE
    if (_console_device == RT_NULL)
    {
        rt_hw_console_output(rt_log_buf);
    }
    else
    {
        rt_device_write(_console_device, 0, rt_log_buf, length);
    }
#else
    rt_hw_console_output(rt_log_buf);
#endif /* RT_USING_DEVICE */
    va_end(args);

    return length;
}
RTM_EXPORT(rt_kprintf);
#endif /* RT_USING_CONSOLE */

这是RT_Thread操作系统中的rt_kprintf函数的源码,rt_kprintf函数的作用是将串口重映射到rt_kprintf,通过rt_kprintf打印信息,但是在代码操作过程中无法打印出浮点数。
打印现象如下

%f
 \ | /
- RT -     Thread Operating System
 / | \     4.1.0 build Jul  8 2022 09:56:08
 2006 - 2021 Copyright by rt-thread team

将源码中的rt_删了之后重新打印现象如下

0.200000
 \ | /
- RT -     Thread Operating System
 / | \     4.1.0 build Jul  8 2022 10:00:11
 2006 - 2021 Copyright by rt-thread team
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

HTIAN1

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值