fprintf的成本

bet*_*n25 2 c c++ embedded printf

我正在用C++开发一个嵌入式应用程序,用于具有有限代码/数据RAM的平台,但是对于文件系统的使用而言是无限的RAM.

在寻找减少代码大小的同时,我意识到排除fprintf()行对生成代码的大小贡献很大.

我的问题是:1.为什么fprintf的成本如此之高?2.如果我排除了fprintf功能,那么生成描述通过应用程序运行的出现的日志文件的替代方法是什么?

pax*_*blo 16

在嵌入式系统中,printf有时可以拖动所有浮点支持格式字符串之类的%f.

更智能的环境将为可选项提供浮点选项printf.

但即使对于整数,也有很多通用代码printf,您可能会发现编写自己的例程更加紧凑,根据您的特定需求量身定制,例如:

outInt (char *buff, int intVal);
outChr (char *buff, char chVal);
outStr (char *buff, char *strVal);
Run Code Online (Sandbox Code Playgroud)

依此类推,用于写入缓冲区,然后outBuff (char *buff)将其发送到文件或标准输出.


例如,如果您控制正在使用的数据(没有字符串溢出,16位二进制补码整数等),您可以使用以下函数:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

void outChr (char *buff, char chVal) {
    *buff++ = chVal;
    *buff = '\0';
}

void outStr (char *buff, char *strVal) {
    strcpy (buff, strVal);
}
Run Code Online (Sandbox Code Playgroud)

 

void outInt (char *buff, int intVal) {
    int divisor = 10000, printing = 0;

    // Special cases.

    if (intVal == -32768) { outStr (buff, "-32768"); return; }
    if (intVal ==      0) { outChr (buff,      '0'); return; }

    // Handle negatives.

    if (intVal < 0) { outChr (buff++, '-'); intVal = -intVal; }

    // Handle non-zero positives <= 32767.

    while (divisor > 0) {
        if ((intVal >= divisor) || printing) {
            outChr (buff++, "0123456789"[intVal/divisor]);
            printing = 1;
        }
        intVal = intVal % divisor;
        divisor /= 10;
    }
}
Run Code Online (Sandbox Code Playgroud)

 

int main (int argc, char *argv[]) {
    char buff[1000];
    int i;
    for (i = 1; i < argc; i++) {
        outInt (buff, atoi (argv[i]));
        printf ("[%s] -> [%s]\n", argv[i], buff);
    }
    return 0;
}
Run Code Online (Sandbox Code Playgroud)

运行此:

pax$ tstprg 32767 10000 9999 10 9 1 0 -1 -9 -10 -99 -10000 -32767 -32768
Run Code Online (Sandbox Code Playgroud)

输出:

[32767] -> [32767]
[10000] -> [10000]
[9999] -> [9999]
[10] -> [10]
[9] -> [9]
[1] -> [1]
[0] -> [0]
[-1] -> [-1]
[-9] -> [-9]
[-10] -> [-10]
[-99] -> [-99]
[-10000] -> [-10000]
[-32767] -> [-32767]
[-32768] -> [-32768]
Run Code Online (Sandbox Code Playgroud)

这些功能的规模应相对较小,因为它们的目标是特定需求,而不是更普遍的printf家庭.


Gra*_*amS 5

它需要合理数量的代码才能提供完全符合ANSI标准的printf功能.

某些嵌入式环境提供的几个不同版本的版本printf要小得多,因为它们只提供所选功能.

例如,用于MSP430IAR C/C++编译器(PDF)提供了printf格式化程序的Tiny,Small,LargeFull实现,Tiny版本仅支持基本说明符(c, d, i, o, p, s, u, X, x, and %),不支持多字节,浮点数,长度修饰符,宽度和精度.

如果您的环境提供此选择,请选择符合您需求的printf(和scanf)版本,并注意这些限制.

如果您的环境不提供此选择,请查看可用的各种"微小"替代printf实现(例如来自SpareTimeLabs的Kustaa Nyholm的这种实现).