繁体   English   中英

fprintf的成本

[英]cost of fprintf

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

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

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

在嵌入式系统中, printf有时会拖动格式字符串(如%f所有浮点支持。

更智能的环境将使printf的浮点选项成为可选项。

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

outInt (char *buff, int intVal);
outChr (char *buff, char chVal);
outStr (char *buff, char *strVal);

等等,用于写入缓冲区,然后用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);
}

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;
    }
}

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;
}

运行此:

pax$ tstprg 32767 10000 9999 10 9 1 0 -1 -9 -10 -99 -10000 -32767 -32768

输出:

[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]

这些功能应该相对较小,因为它们针对特定需求而不是更普遍的printf系列。

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

某些嵌入式环境提供了几个不同版本的printf ,它们相当小,因为它们只提供所选功能。

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

如果您的环境提供此选择,请选择符合您需求的printf (和scanf )版本,并了解其局限性。

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

我可以想到三种情况:

  1. 每次删除fprintf行时,代码大小都会略微下降,当您删除最后一个fprint时,它也会略微下降。
  2. 当您删除最后一个fprint时,代码大小会显着下降。
  3. 每次删除一个fprint实例时,代码大小都会显着下降。

在场景1中,不是fprintf是罪魁祸首,而是你传递给它的字符串文字。 您需要从代码中获取这些字符串,方法是使用非常简短的简洁消息,或者将字符串存储在文件中并通过代码中的某种形式的ID引用它们(尽管这会导致性能下降)

在方案2中,fprintf中 (可能)的罪魁祸首。 它是一个非常复杂的函数,能够以各种方式格式化各种数据类型 - 因此需要相当多的代码空间。 当你删除它的最后一次使用时,链接器会将它从最终的二进制文件中删除,使它们变小。 尝试使用std :: ofstream代替。 如果您只在输出文件中插入(例如)整数和字符串,则只链接用于处理整数和字符串的代码。

场景3是不太可能的 - 并且可能表明fprintf在您使用它的任何地方都被内联

希望这可以帮助

第一个问题的答案取决于您使用的编译器; 你只能通过检查你的编译器得到一个明确的答案。 正如GrahamS所指出的,格式化程序的实现可能很复杂。

尝试使用fputs而不是fprintf来避免格式​​化程序。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM