将 C++ 编译为尽可能小的大小

Posted

技术标签:

【中文标题】将 C++ 编译为尽可能小的大小【英文标题】:Compiling a C++ to smallest possible size 【发布时间】:2013-09-18 15:56:58 【问题描述】:

我很好奇应该如何将一个相对简单的 C++ 脚本编译为尽可能小的可执行文件大小。

不用过多讨论为什么这个程序会有用,这里是我的代码:

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

using namespace std;

unsigned long long inputAdjust(const string myinput) 
    unsigned long long myadjust;
    if (myinput=="B") 
        myadjust=1;
     else if (myinput=="K") 
        myadjust=1024;
     else if (myinput=="M") 
        myadjust=1048576;
     else if (myinput=="G") 
        myadjust=1073741824;
     else 
        myadjust=1;
    
    return myadjust;


long long asmAnswer (const string myinput, const unsigned long long fir, const unsigned long long sec) 
    unsigned long long myanswer;
    if (myinput=="A") 
        myanswer = fir + sec;
     else if (myinput=="S") 
        myanswer = fir - sec;
     else if (myinput=="M") 
        myanswer = fir * sec;
     else 
        myanswer = fir + sec;
    
    return myanswer;


double dAnswer (const unsigned long long fir, const unsigned long long sec) 
    double myanswer;
    myanswer = (double)fir/sec;
    return myanswer;


void outputAnswer (const string myinput, const long long myanswer) 
    if (myinput=="B") 
        printf("%lld",myanswer);
     else if (myinput=="K") 
        printf("%.2f",(double)(myanswer/1024));
     else if (myinput=="M") 
        printf("%.2f",(double)(myanswer/1048576));
     else if (myinput=="G") 
        printf("%.2f",(double)(myanswer/1073741824));
     else if (myinput=="O") 
        if (myanswer>0) 
            if (myanswer<1024 && myanswer>-1024) 
                printf("%lld b",myanswer);
             else if (myanswer<1048576 && myanswer>-1048576) 
                printf("%.2f kb",(double)(myanswer/1024));
             else if (myanswer<1073741824 && myanswer>-1073741824) 
                printf("%.2f mb",(double)(myanswer/1048576));
             else 
                printf("%.2f gb",(double)(myanswer/1073741824));
            
        
     else  //assume bytes
        printf("%lld",myanswer);
    


void outputAnswer (const string myinput, const double myanswer) 
    if (myinput=="P") 
        printf("%.3f",(myanswer*100.0));
     else 
        printf("%.3f",myanswer);
    


int main(int argc, char* argv[])  
    if (argc < 5) 
        // If we have less than 5 arguments, output the usage 
        string filename = argv[0];
        printf("\nUsage: bytemath.exe BKMG BKMGO[P] ASMD FirstNum SecondNum\n    First <OPERATOR> Second\n");
        return 0;
     else 
        string input =  argv[1];
        string output = argv[2];
        string oper =   argv[3];
        unsigned long long first =  atoll(argv[4]);
        unsigned long long second = atoll(argv[5]);
        unsigned long i_adjust;
        unsigned long o_adjust;

        i_adjust = inputAdjust(input);
        first *= i_adjust;
        second*= i_adjust;

        if (oper=="D")  // we want to divide so need to use a double rather than long
            double answer;
            answer = dAnswer(first, second);
            outputAnswer(output, answer);
         else  // otherwise do +, -, or *
            long long answer;
            answer = asmAnswer(oper, first, second);
            outputAnswer(output, answer);
        

        return 1;
    

基本上它对大数进行数学运算,因为批处理文件只能处理 32 位无符号整数。我可能只使用 VBS 之类的东西,但这是我目前正在使用的解决方案。

我需要程序是独立的,所以它必须静态链接到库。通过用printf 替换所有cout 命令,我能够将大小从~570kb 减小到~148kb,但我想知道我还能做些什么来减小文件大小。

我正在用 MiniGW 4.6 编译它,这是我目前的编译命令:

g++ -Os -s -static bytemath.cpp -o bytemath.exe

在不重写太多代码的情况下,我还能做些什么来减小文件大小?

谢谢。

编辑

两大节省者正在摆脱&lt;iostream&gt;&lt;string&gt;,我可以通过将所有cout 命令替换为printf 并将我的字符串比较替换为char* 比较来实现。对于字符,我需要确保访问数组的第 0 个元素并将其与单引号而不是双引号中的字符进行比较(即if (myinput[0]=='P') 而不是if (myinput=="P") )。

再次感谢大家! 570kb 到 18kb,适合我!

【问题讨论】:

你真的不需要你所有的 printf 调用。使用你的 if 语句来计算你想要输出的值,然后用一个 printf 输出。 我是这样做的,因为有时我输出long long,有时我输出float。自从我使用 c++ 以来已经有一段时间了,但对我来说这更容易。使用下面的提示将string 的所有实例替换为char* 有效,但我想这也会有所帮助,但修复该问题所需的时间不会为该项目节省太多空间(现在它已降至 18kb)。不过感谢您的提示! 【参考方案1】:

只是猜测,但是:删除字符串并用枚举和/或 char* 替换它们。无论如何,您大多使用枚举之类的字符串,输入字符上的简单 if 可以为您提供枚举。

【讨论】:

啊,我能做到。但是,我不熟悉枚举。确实,我使用的所有字符串都是在if 语句中进行比较,而且我只查看过 1 个字符。这个工具只会被我用于一个非常特定的目的,所以在输入参数时我不需要很多错误检查和类似的事情。我将只使用普通的 char*,看看我是否可以这样进行比较。 是的,不确定我是否可以直接进行查找和替换,但我想我只是用char* 替换了string 的每个实例并摆脱了#include &lt;string&gt; 并减少了它低至 18kb。对我来说已经足够好了!感谢您的提示。 啊,没关系,该程序现在无法运行。如果 myinput 的类型是char*,我认为我不能做if (myinput=="A")。好的,我需要弄清楚如何进行比较。不过,我走在正确的轨道上,谢谢。 抱歉所有的编辑,好的,我想我们现在都很好。在 if 语句中,我需要做 myinput[0]=='P' 因为我关心的只是参数的第一个字母。谢谢大家!【参考方案2】:

如果您已完成调试,您可以在编译器命令中添加“-s”。 '-s' 表示去除所有符号。 剥离或修改附加到汇编器和链接编辑器输出的符号表可以节省程序调试后的空间,并且还会限制动态绑定的符号

另外,尝试通过引用而不是值传递std::string 改变 inputAdjust(const string myinput)inputAdjust(const string&amp; myinput) 这可能无助于减少二进制大小,但会避免在运行时进行堆分配。

【讨论】:

我已经很久没有用 C++ 做任何事情了,但我不认为我在做任何调试。我只是用我在评论中包含的 g++ 命令编译这个 .cpp 文件。有什么我应该先运行的(比如制作一个 .a 文件?)然后运行编译器吗? 你的编译命令中已经有了-s(假设对mingw也是如此)。

以上是关于将 C++ 编译为尽可能小的大小的主要内容,如果未能解决你的问题,请参考以下文章

如何将javascript代码编译为c++或java

是否有编译为机器代码的 C C++ C# 编译器 [关闭]

使用 emcc 将 C++ 代码编译为 WASM 的问题

#ifdef 标志来区分 gcc 和 g++ 编译器? [复制]

如何将 c、c++ 和 python 代码编译为“Released/Final”版本? [关闭]

为啥将class反编译为java后,java直接编译时有错误