Can someone tell me of a good C++ library for handling (doing operations etc...) with arbitrarily large numbers (it can be a library that handles arbitrary precision floats too, but handling integers is more important)?
Please only refer to libraries that YOU used and tell me how did you managed to set it up and pick it up, maybe with a very minimalistic example or something (basically if the mentioned library lacks good documentation provide some input of your own).
For the record I'm using Windows 7 on an x64 machine, CodeBlocks as my IDE, and the latest MinGW as the compiler.
Libraries I tried:
vlint (not enough operations, works fine for small stuff though)
bigint (easy to set it up, compile errors and not much documentation (from which errors might be derived))
ttmath (seemed promising, compiled some BIG example programs and ran after some fixes because of compiling errors, incomprehensible syntax because of virtually no documentantion)
gmp (couldn't even set it up)
p.s. Removed the 'rant part of the question' that basically explained why I'm asking something that was asked a lot of times on Stackoverflow so people would read it to the end.
--> UPDATE
So i picked an answer that wasn't a direct answer to my initial question but helped me a lot to solve this and i will post some of my findings to help other c++ newbies like me to get started working with very big numbers without struggling with libraries for days like i did in an easy step by step micro-guide.
Stuff i was using (keep this in mind to follow the guide):
Windows 7 Ultimate x64
Amd k10 x64 (some libraries won't work with this, others will behave differently, others are custom taylored to amd k10 so this won't only help you with the library i used but possibly with others too)
Code::Blocks 10.05 the version without MinGW included, file name "codeblocks-10.05-setup.exe" (installed on C:\Program Files (x86)\CodeBlocks)
MinGW packages (binutils-2.15.91-20040904-1.tar.gz gcc-core-3.4.2-20040916-1.tar.gz gcc-g++-3.4.2-20040916-1.tar.gz mingw-runtime-3.11.tar.gz w32api-3.8.tar.gz) extracted on C:\MinGW
TTMath 0.9.2 file name "ttmath-0.9.2-src.tar.gz" unzipped and copied the folder "ttmath" to the folder "C:\CPPLibs" (which is the folder where i put my c++ libraries into)
What to do to set it all up
Go to Code:Blocks > Settings > Compiler and Debugger (My compiler was detected automatically here. If this doesn't happen with you, on "Selected Compiler" select "GNU GCC Compiler" and click "Set as Default" then on "Toolchain Exectables" on "Compilers installation directory you can choose the installation directory of the compiler or attempt to auto-detect" and with that sorted on "C++ Compiler" select or write "mingw32-g++.exe". If this happens to you just do this, on "Selected Compiler" select "GNU GCC Compiler" and click "Set as Default").
Without leaving "Code:Blocks > Settings > Compiler and Debugger" and with the above sorted out, go to "Search Directories" and then "Compiler" click "Add" and choose the folder where you store your libraries or where you put your "ttmath" folder (in my case C:\CPPLibs) then go to "Linker" and do the same thing.
To start coding with the "ttmath" library you have to put this line #include <ttmath/ttmath.h> before the main function (NOTE: If you use a 64bit system you WILL get a lot of errors if you don't also put this line #define TTMATH_DONT_USE_WCHAR BEFORE this line #include <ttmath/ttmath.h>, i was struggling with this crap until i found the fix that some other guy that was also struggling found and posted on the web and it worked for me) p.s. i think it's only for 64bit systems but if you do get errors just because of including the "ttmath.h" header file it's most likely because of that.
Declaring variables that will have big integer values has to be done like so: ttmath::UInt<n> a,b,c; where "a,b,c" are your variables and "n" is the size of the numbers you can store in the variables in this form "2^(32*n)-1" for 32bit systems and this form "2^(64*n)-1" for 64bit systems
Assigning values to variables if you do this a = 333; (and the number in place of 333 is bigger than the "long int" standard data type on c++) it won't compile because assigning values to variables like this independently of the size you specified earlier the integer can be just as big as the the "long int" standard data type on c++ (i figured this one on my own, the hard way), also even if you use a value that is smaller and it compiles alright and then you run your program and it tries to write to this variable a bigger number than the number that the mentioned "long int" standard data type can handle, then your math is going to be wrong so watch this: to assign a value to a variable the right way you have to assign it like so a = "333"; (yes i know you are pretty much treating it as a string this way but it will do operations just fine with no problems whatsoever and if you decide to "cout" the variable it will never be an exponential or scientific notation result like you get using standard integer data types without being coupled with some 'extra statements' to display the number just right)
p.s. Using this simple rules to work with integers and this library i computed fibonacci numbers up to the 100.000th number with a simple program (that took like 3min to code) in 15 to 20 seconds and the number occupied like 3 pages so besides being a practical library once you get to know how it works (that you had virtually no help before, some samples of the ttmath website are pretty misleading, but now you do have some help) it also seems pretty efficient, i confirmed that the 100.000th number is probably right because i increased the size (the "n") from 10000 to 50000 and the number retained the size and the initial and final digits were the same. This is the source code i used, i used a VERY BIG number for the integer size just to test, i didn't actually bothered to see on what lenght the program would start do do stuff wrong but i know that the lenght of up to the 10.000th fibonacci number won't surpass the lenght that i defined because before this i made the program 'cout' every result until it got to 10.000th and it was always growing. I also checked the first numbers of the sequence before when i paused the program and i was seeing the 'digits grow' and confirmed the first fibonacci numbers of the sequence and they were correct. NOTE: This source code will only display the number of the fibonacci sequence that you want to know, it will only show you the numbers "growing" if you uncomment the commented lines.
#define TTMATH_DONT_USE_WCHAR
#include <ttmath/ttmath.h>
#include <iostream>
using namespace std;
int main () {
int fibonaccinumber;
cin >> fibonaccinumber;
cin.ignore();
ttmath::UInt<10000> fibonacci1,fibonacci2,fibonacci3;
fibonacci1 = 1;
fibonacci2 = 1;
//cout << "1. " << fibonacci1 << "\n2. " << fibonacci2 << "\n";
for(int i=3;i<=fibonaccinumber;i++)
{fibonacci3 = fibonacci1 + fibonacci2;
// cout << i << ". " << fibonacci3 << "\n";
fibonacci1=fibonacci2;
fibonacci2=fibonacci3;}
cout << "the " << fibonaccinumber << "th fibonacci number is " << fibonacci2;
string endprog;
getline(cin,endprog);
return 0;}
I didn't tinkered with arbitrary precision floats of this lbrary yet but when i do i will continue to expand this guide if i see that people are interested in it, thanks for all the comments and answers.
The official site (http://www.ttmath.org/) has samples of using integers (ttmath::Int<2> a,b,c;) and floating points (ttmath::Big<1,2> a,b,c;) both. Just treat these like high precision int/float without members and everything should be fine. If the error remains, can you post the full error message, and the lines of code that it errored on?
The Boost.Multiprecision library supports arbitrarily long integers, real numbers and ratios. It also allows you to use different back-ends which have different performance characteristics and licensing terms.
A few possibilities are MIRACL, NTL and LIP.
Related
So I was recently upgrading an old c++ project that was built using the Visual Studio 2012 - Windows XP (v110_xp) platform toolset. In the code of this project, there is some very precise double calculations happening to require up to 20 characters of precision. These doubles were then saved to a string and printed off using the printf APIs. Here is an example of what something that would happen in this project:
double testVal = 123.456789;
// do some calculations on testVal
char str[100] = { 0 };
sprintf(str, "%.20le", testVal);
After this operation str = "1.23456789000...000e+02", which is what is expected.
However, once I update the project to be compatible with Visual Studio 2019, using Visual Studio 2019 (v142) platform Toolset, with c++ 17, the above-mentioned code produces different outputs for str.
After the call to sprintf to format the value to a string, str = "1.23456789000...556e+02". This problem isn't localized to this one value, there are even more aggregious problems. For example, one of the starting values of "2234332.434322" after the sprintf formatting gets changed to "2.23433324343219995499e+07"
From all the documentation I've read with the "l" format code, it should be the correct character for converting long doubles to the string. This behavior feels like textbook float->double conversion though.
I tried setting the projects floating-point model build an argument to precise, strict, and then fast to see if any of these options would help, but it does not have an effect on the problem.
Does anyone know why this is happening?
Use the brand new Ryu (https://github.com/ulfjack/ryu) or Grisu-Exact (https://github.com/jk-jeon/Grisu-Exact) instead which are much faster than sprintf and guaranteed to be roundtrip-correct (and more), or the good old Double-Conversion (https://github.com/google/double-conversion) which is slower than the other two but has the same guarantees, still much faster than sprintf, and is battle-tested.
(Disclaimer: I'm the author of Grisu-Exact.)
I'm not sure if you really need to print out exactly 20 decimal digits, because I personally had rare occasions where the number of digits mattered. If the sole purpose of having 20 digits is just to not lose any precision, then the above mentioned libraries will definitely provide you better (and shorter) results. If the number of digits must be precisely 20 for some reasons, then well, Ryu still provides such a feature (it's called Ryu-printf) which again has the roundtrip-guarantee and much faster than sprintf.
EDIT
To elaborate more on the last sentence, note that in general it is impossible to have the roundtrip guarantee if the number of digits is fixed, because, well, if that fixed number is too small, say, 3, then there is no way to distinguish 0.123 and 0.1234. However, 20 is big enough so that the best approximation of the true value (which is what Ryu-printf produces) is always guaranteed to be roundtrip-correct.
This question already has answers here:
What should main() return in C and C++?
(19 answers)
Closed 5 years ago.
I am working with a MATLAB optimization platform for black-box cost functions (BBCF).
To make the user free-handed, the utilized BBCF can be any executable file which inputs the input parameters of BBF and must output (return) the cost value of BBCF, so that the MATLAB BBCF optimizer finds the best (least cost) input parameter.
Considering that, from the one hand, my BBCF is implemented in C++, and from the other hand the cost value is a double (real number), I need to compile my code to an EXE file that outputs (returns) double.
But, to the best of my knowledge, when I compile a C++ code to EXE, it "mainly" compiles the main() function and its output is the output of main() function (i.e. 0 if running successful!).
An idea could be using a main function that returns double, and then, compiling such main() to EXE but, unfortunately, it is not possible in C++ (as explained in this link or as claimed in the 3rd answer of this question to be a bug of C++ neither of which are business of this question).
Can anyone provide an idea by which the EXE compiled form of a C++ code, outputs (returns) a double value?
This is not 'a bug in C++' (by the way, the bug might be in some C++ compiler, not in the language itself) - it's described in the standard that main() should return an integer:
http://en.cppreference.com/w/cpp/language/main_function
Regarding how to return a non-int from an executable, there are a couple of ways to do that. Two simplest (in terms of how to implement them) solutions come to my mind:
Save it to a file. Then either monitor that file in Matlab for changes (e.g. compare timestamps) or read after each execution of your EXE file depending on how you're going to use it. Not very efficient solution, but does the job and probably the performance penalty is negligible to that of your other calculations.
If you are fine with your cost value losing some numerical accuracy, you can just multiply the double value by some number (the larger this number, the more decimal places you will retain). Then round it, cast it to an int, have it returned from main(), cast it back to double in matlab and divide by the same number. The number used as the multiplier should be a power of 2 so that it doesn't introduce additional rounding errors. This method might be particularly useful if your cost value takes the values limited to the range [0, 1] or if you can normalize it to these values and you know that variations less than some threshold are not important.
In English, 'shall' is an even stronger imperative than 'must'.
Making a change like this would require changes to the operating system and shell. Such changes are unlikely to happen.
The easiest way to pass a double return would to to write it to standard output. Alternatively there are several methods available for interprocess communication.
I'm debugging a very complex C++ function that gives me some unexpected results under some inputs. I'd like to compare code executions under different input so that I find out what part causes me bug. The tool that can compare code execution paths is what I am looking for. Please let me know if such a tool exists. Or otherwise if there's some techniques I can employ to do the same thing?
To describe my problem concretely, here I'm using a contrived example.
Say this is the function in pseudocode,
double payTax(double income)
{
if (income < 10000)
return noTax();
else if ( 10000 < income < 30000)
return levelOneTax();
else if (30000 < income < 48000)
return levelTwoTax();
else
return levelThreeAboveTax();
}
Given input 15000, the function computes the correct amount of tax, but somehow input 16000 gives an erroneous tax amount. Supposedly, input 15000 and 16000 would cause the function to go through exactly the same execution paths; on the other hand, if they go different paths, then something must have gone wrong within the function. Therefore, a tool that compares execution paths would reveal enough information that could help me quickly identify the bug. I'm looking for such a tool. Preferably compatible with Visual Studio 2010. It would be better if such a tool also keeps values of variables.
P.S. debugging is the last thing I want to do because the code base I am working with is much much bigger and complex than the trivial payTax example.
Please help. Thanks.
The keywords you are looking for is "code coverage" or "coverage analysis" or "code coverage analysis".
Which tool you use will naturally depend on the rest of your environment.
I know that this question is almost ten years old now, but I'll still give my answer here, since it may be useful for a random googler.
The approach does not require any additional 3rd party tools, except maybe a usual text diff application to compare text files with execution paths.
You'll need to output the execution path yourself from your application, but instead of adding logging code in every function, you'll use special support from the compiler to make it call your handlers upon each function entry and exit. Microsoft compiler calls it Hook Functions and require separate flags for hooking function entering (/Gh) and exiting (/GH). GNU C++ compiler calls it instrumentation functions and requires a single -finstrument-functions flag for both.
Given those flags the compilers will add special prologue and epilogue code for each function being compiled, which will call special handlers, one for enter and one for exit. You'll need to provide the implementation of those handlers yourself. On GNU C++ the handlers are already passed with the pointers to the function being entered into or exited from. If you're on MSVC++, you'll need to use the return of _ReturnAddress intrinsic with some modification to get the address of the function.
Then you can just output the address as is and then use something line add2line tool to translate the address to function name. Or you can go one step further and make the translation yourself.
On MSVC++ you can use DbgHelp API and specifically SymInitialize and SymFromAddr helpers to translate the address into the function name. This will require your application to be compiled with debug information.
On GNU C++ you may probably want to use backtrace_symbols to translate the address into function name, and then maybe __cxa_demangle to demangle the returned name. This will probably require your executable to be built with -rdynamic.
Having all this in place you can output the name of each called function with the needed indent and thus have the call path. Or even do some fancier stuff like this, this or this.
You can use this MSVC++ code or this GCC code as a starting point, or just use your favorite search engine for other examples which are plenty.
The tool you want is printf or std::cerr!
And you have a substantial error in your code: a statement like if ( 10000 < income < 30000) will not work as expected! You want to write it like if( 10000 < income && income < 30000 ).
And to keep testing simple, please use curly brackets as in:
if( 10000 < income && income < 30000 ) {
return levelOneTax();
} else if( ...
Because then it will be much easier to add debug output, as in:
if( 10000 < income && income < 30000 ) {
std::cerr << "using levelOneTax for income=" << income << std::endl;
return levelOneTax();
} else if( ...
EDIT
BTW: "a tool that compares execution paths would reveal enough information [...]", BUT in the sense you are expecting, such a tool would reveal TOO MUCH information to handle. The best thing you can do is debugging and verifying that your code is doing what you expect it to do. A "code coverage" tool would probably be too big for your case (and also such tools are not cheap).
I am planning to use an Arduino programmable board. Those have quite limited flash memories ranging between 16 and 128 kB to store compiled C or C++ code.
Are there ways to estimate how much (standard) code it will represent ?
I suppose this is very vague, but I'm only looking for an order of magnitude.
The output of the size command is a good starting place, but does not give you all of the information you need.
$ avr-size program.elf
text data bss dec hex filename
The size of your image is usually a little bit more than the sum of the text and the data sections. The bss section is essentially compressed because it is all 0s. There may be other sections which are relevant which aren't listed by size.
If your build system is set up like ones that I've used before for AVR microcontrollers then you will end up with an *.elf file as well as a *.bin file, and possibly a *.hex file. The *.bin file is the actual image that would be stored in the program flash of the processor, so you can examine its size to determine how your program is growing as you make edits to it. The *.bin file is extracted from the *.elf file with the objdump command and some flags which I can't remember right now.
If you are wanting to know how to guess-timate how your much your C or C++ code will produce when compiled, this is a lot more difficult. I have observed a 10x blowup in a function when I tried to use a uint64_t rather than a uint32_t when all I was doing was incrementing it (this was about 5 times more code than I thought it would be). This was mostly to do with gcc's avr optimizations not being the best, but smaller changes in code size can creep in from seemingly innocent code.
This will likely be amplified with the use of C++, which tends to hide more things that turn into code than C does. Chief among the things C++ hides are destructor calls and lots of pointer dereferencing which has to do with the this pointer in objects as well as a secret pointer many objects have to their virtual function table and class static variables.
On AVR all of this pointer stuff is likely to really add up because pointers are twice as big as registers and take multiple instructions to load. Also AVR has only a few register pairs that can be used as pointers, which results in lots of moving things into and out of those registers.
Some tips for small programs on AVR:
Use uint8_t and int8_t instead of int whenever you can. You could also use uint_fast8_t and int_fast8_t if you want your code to be portable. This can lead to many operations taking up only half as much code, because int is two bytes.
Be very aware of things like string and struct constants and literals and how/where they are stored.
If you're not scared of it, read the AVR assembly manual. You can get an idea of the types of instructions, and from that the type of C code that easily maps to those instructions. Use that kind of C code.
You can't really say there. The length of the uncompiled code has little to do with the length of the compiled code. For example:
#include <iostream>
#include <vector>
#include <string>
#include <algorithm>
int main()
{
std::vector<std::string> strings;
strings.push_back("Hello");
strings.push_back("World");
std::sort(strings.begin(), strings.end());
std::copy(strings.begin(), strings.end(), std::ostream_iterator<std::string>(std::cout, ""));
}
vs
#include <iostream>
#include <vector>
#include <string>
#include <algorithm>
int main()
{
std::vector<std::string> strings;
strings.push_back("Hello");
strings.push_back("World");
for ( int idx = 0; idx < strings.size(); idx++ )
std::cout << strings[idx];
}
Both are the exact same number of lines, and produce the same output, but the first example involves an instantiation of std::sort, which is probably an order of magnitude more code than the rest of the code here.
If you absolutely need to count number of bytes used in the program, use assembler.
Download the arduino IDE and 'verify' some of your existing code, or look at the sample sketches. It will tell you how many bytes that code is, which will give you an idea of how much more you can fit into a given device. Picking a couple of the examples at random, the web server example is 5816 bytes, and the LCD hello world is 2616. Both use external libraries.
Try creating a simplified version of your app, focusing on the most valuable feature first, then start adding up the 'nice (and cool) stuff to have'. Keep an eye on the byte usage shown in the Arduino IDE when you verify your code.
As a rough indication, my first app (LED flasher controlled by a push buttun) requires 1092 bytes. That`s roughly 1K out of 32k. Pretty small footprint for C++ code!
What worries me most is the limited amount of RAM (1 Kb). If the CPU stack takes some of it, then there isn`t much left for creating any data structures.
I only had my Arduino for 48 hrs, so there is still a lot to use it effectively ;-) But it's a lot of fun to use :).
It's quite a bit for a reasonably complex piece of software, but you will start bumping into the limit if you want it to have a lot of different functionality. Also, if you want to store quite a lot of static strings and data, it can eat into that quite quickly. But 32 KB is a decent amount for embedded applications. It tends to be RAM that you have problems with first!
Also, quite often the C++ compilers for embedded systems are a lot worse than the C compilers.
That is, they are nowhere as good as C++ compilers for the common desktop OS's (in terms of producing efficient machine code for the target platform).
At a linux system you can do some experiments with static compiled example programs. E.g.
$ size `which busybox `
text data bss dec hex filename
1830468 4448 25650 1860566 1c63d6 /bin/busybox
The sizes are given in bytes. This output is independent from the executable file format, since the sizes of the different sections inside the file format. The text section contains the machine code and const stufff. The data section contains data for static initialization of variables. The bss size is the size of uninitialized data - of course uninitialized data does not need to be stored in the executable file.)
Well, busybox contains a lot of functionality (like all common shell commands, a shell etc.).
If you link own examples with gcc -static, keep in mind, that your used libc may dramatically increase the program size and that using an embedded libc may be much more space efficient.
To test that you can check out the diet-libc or uclibc and link against that. Actually, busybox is usually linked against uclibc.
Note that the sizes you get this way give you only an order of magnitude. For example, your workstation probably uses another CPU architecture than the arduino board and the machine code of different architecture may differ, more or less, in its size (because of operand sizes, available instructions, opcode encoding and so one).
To go on with rough order of magnitude reasoning, busybox contains roughly 309 tools (including ftp daemon and such stuff), i.e. the average code size of a busybox tool is roughly 5k.
My executable was 364KB in size. It did not use a Vector2D class so I implemented one with overloaded operators.
I changed most of my code from
point.x = point2.x;
point.y = point2.y;
to
point = point2;
This resulted in removing nearly 1/3 of my lines of code and yet my exe is still 364KB. What exactly causes it to grow in size?
The compiler probably optimised your operator overload by inlining it. So it effectively compiles to the same code as your original example would. So you may have cut down a lot of lines of code by overloading the assignment operator, but when the compiler inlines, it takes the contents of your assignment operator and sticks it inline at the calling point.
Inlining is one of the ways an executable can grow in size. It's not the only way, as you can see in other answers.
What makes EXE’s grow in size?
External libraries, especially static libraries and debugging information, total size of your code, runtime library. More code, more libraries == larger exe.
To reduce size of exe, you need to process exe with gnu strip utility, get rid of all static libraries, get rid of C/C++ runtime libraries, disable all runtime checks and turn on compiler size optimizations. Working without CRT is a pain, but it is possible. Also there is a wcrt (alternative C runtime) library created for making small applications (by the way, it hasn't been updated/maintained during last 5 years).
The smallest exe that I was able create with msvc compiler is somewhere around 16 kilobytes. This was a windows application that displayed single window and required msvcrt.dll to run. I've modified it a bit, and turned it into practical joke that wipes out picture on monitor.
For impressive exe size reduction techniques, you may want to look at .kkrieger. It is a 3D first person shooter, 96 kilobytes total. The game has a large and detailed level, supports shaders, real-time shadows, etc. I.e. comparable with Saurbraten (see screenshots). The smallest working windows application (3d demo with music) I ever encountered was 4 kilobytes big, and used compression techniques and (probably) undocumented features (i.e. the fact that *.com executbale could unpack and launch win32 exe on windows xp)..
In most cases, size of *.exe shouldn't really bother you (I haven't seen a diskette for a few years), as long as it is reasonable (below 100 megabytes). For example of "unreasonable" file size see debug build of Qt 4 for mingw.
This resulted in removing nearly 1/3 of my lines of code and yet my exe is still 364KB.
Most likely it is caused by external libraries used by compiler, runtime checks, etc.
Also, this is an assignment operation. If you aren't using custom types for x (with copy constructor), "copy" operation is very likely to result in small number of operations - i.e. removing 1/3 of lines doesn't guarantee that your code will be 1/3 shorter.
If you want to see how much impact your modification made, you could "ask" compiler to produce asm listing for both versions of the program then compare results (manually or with diff). Or you could disasm/compare both versions of executable. BUt I'm certain that using GNU strip or removing extra libraries will have more effect than removing assignment operators.
What type is point? If it's two floats, then the compiler will implicitly do a member-by-member copy, which is the same thing you did before.
EDIT: Apparently some people in today's crowd didn't understand this answer and compensated by downvoting. So let me elaborate:
Lines of code have NO relation to the executable size. The source code tells the compiler what assembly line to create. One line of code can cause hundreds if not thousands of assembly instructions. This is particularly true in C++, where one line can cause implicit object construction, destruction, copying, etc.
In this particular case, I suppose that "point" is a class with two floats, so using the assignment operator will perform a member-by-member copy, i.e. it takes every member individually and copies it. Which is exactly the same thing he did before, except that now it's done implicitly. The resulting assembly (and thus executable size) is the same.
Executables are most often sized in 'pages' rather than discrete bytes.
I think this a good example why one shouldn't worry too much about code being too verbose if you have a good optimizing compiler. Instead always code clearly so that fellow programmers can read your code and leave the optimization to the compiler.
Some links to look into
http://www2.research.att.com/~bs/bs_faq.html#Hello-world
GCC C++ "Hello World" program -> .exe is 500kb big when compiled on Windows. How can I reduce its size?
http://www.catch22.net/tuts/minexe
As for Windows, lots of compiler options in VC++ may be activated like RTTI, exception handling, buffer checking, etc. that may add more behind the scenes to the overall size.
When you compile a c or c++ program into an executable, the compiler translates your code into machine code, and applying optimizations as it sees fit.
But simply, more code = more machine code to generate = more size to the executable.
Also, check if you have lot of static/global objects. This substantially increase your exe size if they are not zero initialized.
For example:
int temp[100] = {0};
int main()
{
}
size of the above program is 9140 bytes on my linux machine.
if I initialize temp array to 5, then the size will shoot up by around 400 bytes. The size of the below program on my linux machine is 9588.
int temp[100] = {5};
int main()
{
}
This is because, zero initialized global objects go into .bss segment, which ill be initialized at once during program startup. Where as non zero initialized objects contents will be embedded in the exe itself.