Frage

I am curious about how I should go about compiling a relatively simple C++ script to its smallest possible executable size.

Without going too much into why this program will be useful, here is my code:

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

Basically it does math operations on large numbers because batch files can only work with 32-bit unsigned integers. I could probably just use something like VBS but this is the solution I'm working with at the moment.

I need the program to be standalone, so it has to statically link to libraries. I was able to get the size down from ~570kb to ~148kb by replacing all the cout commands with printf, but I'm wondering what else I can do to get the file size down.

I am compiling this with MiniGW 4.6, and this is my compile command at the moment:

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

Anything else I can do to reduce the file size without too much code rewriting?

Thanks.

EDIT

The two big savers were getting rid of <iostream> and <string>, which I was able to do by replacing all my cout commands with printf and replacing my string comparisons with a char* comparison. For the chars, I needed to make sure to access the 0th element of the array and compare it to a char in single quotes rather than double quotes (i.e. if (myinput[0]=='P') { rather than if (myinput=="P") {).

Thanks again everyone! 570kb to 18kb, works for me!

War es hilfreich?

Lösung

Just a guess, but: remove the strings and replace them by enums and/or char*. You mostly use those strings like enums anyways and a simple if on the input chars can get you the enums.

Andere Tipps

If you have finished debugging, you can add '-s' to your compiler command. '-s' means strip all symbols. To strip or modifies the symbol table attached to the output of the assembler and link editor can save space after a program has been debugged, and it will also limit dynamically bound symbols

In addition, try to pass std::string by ref instead of by value change inputAdjust(const string myinput) to inputAdjust(const string& myinput) This may not help reduce binary size, but it will avoid heap allocation at runtime.

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top