簡體   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