Home > Back-end >  Large array in C works, but why?
Large array in C works, but why?

Time:01-12

Why can I compile and run this code? Isn't the array too large? How is memory allocated to this array?

#include <iostream>
#define Nbig 10000000000000000
int main() {
int x[Nbig];
x[Nbig-1]=100;
    std::cout <<"x[Nbig-1]= "<< x[Nbig-1] <<"\n\n";
    return 0;
}

I thought when a static array is declared, a chunk of RAM should be allocated to it and when I assign a value to say x[1000], the memory bytes at the 'x 1000*4' address (4 for int and x the address of the first element) should represent the value. I tried googling and read about static and dynamics allocation, heap and stack, RAM itsel but didn't find my answer anywhere. Additional information that might help: I'm using linux with 32GB RAM and and compile the code with gcc.

CodePudding user response:

I thought when a static array is declared, a chunk of RAM should be allocated to it

That is an implementation detail of the C implementation. You are asking for an array of the given size on the language level. The compiler has to compile the program in such a way that it behaves as the language specifies programs using arrays to behave. The language standard makes no mention of RAM or a stack and allows arrays of any arbitrary size up to an implementation-defined limit. How the compiler uses memory to provide for this behavior of the program is completely up to the compiler. If it can figure out that e.g. no RAM use is required to make the program behave equivalently to the specification, then it doesn't need to use any.

Since you use only one element of the array, there is clearly no need to reserve memory for the whole array and using less memory than asked for is also a desirable optimization, so it is not surprising that a compiler would choose to not allocate memory for the rest of the array. Even further it is obvious that you are only using the single element of the array to pass a constant to std::cout, so the compiler can completely avoid reserving memory for the array and just pass the constant directly to std::cout << in a register.

CodePudding user response:

If the address of an automatic-duration object is never exposed to outside code or otherwise used in ways a compiler can't fully track, and if a compiler can "understand" everything that is done with the object, the compiler need not allocate actual storage for the object.

In this case, some compilers would probably be able to see that only one element of the array is ever read, and it's always written with the value 100, and thus there is no need to allocate any storage for the array. Instead, any operation that would read the array may be replaced with operation that loads the constant 100.

CodePudding user response:

FYI, this code:

int main() {
    int x[Nbig];

attempts to allocate x on the stack (it's local to the function main and is not explicitly declared static). Typically, the max size of the stack is somewhere around a couple of megabytes, so your array won't fit. Most compilers know this and will refuse to compile this code. If it does compile, it will almost certainly fail at runtime.

In your case, the compiler will have optimized the whole thing away, since you only use one element.

If you need a compile-time array that can be allocated, make it static, like this:

int main() {
    static int x[Nbig];

Or:

 int x[Nbig];
 int main() {

(ignoring the fact that your #define may have been truncated)

This will allocate the array in the fixed-size data segment.

  • Related