If I declare an array double x[n] where n is either a constant or an int variable, I can get it's size during runtime. But if I allocate memory using malloc this does not happen. Is this because of stack vs heap memory allocation ? If so how are array sizes for global variables determined and why can't I declare variable length arrays as global variables ? and how does deallocation work since you need to know how much memory to free ?
2 Answers
The answer to basically all of your questions is that the memory allocator privately knows how much memory it allocated, but not the type of your object. In fact, it might only know how many blocks of some fixed size it allocated, not necessarily the same as the number of bytes requested. Therefore it does not know how many elements that "array" contains, or even if it's being used as an array at all.
You are expected to keep track of usage-specific information yourself if you need it. You simply request however many bytes you need and then use that memory however you choose. It is not the allocator's responsibility to assist you with this, which gives you full flexibility to do whatever you want.
The array x in your example has a known type and size at compile time, or can be inferred at runtime. In other words, the compiler knows that it should push some number of bytes onto the stack based on the size value and use them as an array of the defined type.
It makes less sense to have VLAs at global scope, since the whole point of the VLA is that it is allocated based on the variable size when entering a block scope. The global scope is only entered once when your program is initialized.
8 Comments
sizeof(x) is constant. The value is known at compile time and hardcoded into your compiled program for any instructions that use the value or other constant derivatives of the value (e.g. sizeof(x) / sizeof(*x) is also constant and is computed at compile time)x is only known in the scope in which x is declared. If you pass x as an argument to another function, that other function does not know its size.During translation, the compiler keeps track of all variable definitions and their sizes. Except for VLAs, the sizeof operator is evaluated at compile time, not runtime. How the sizes of VLAs are tracked is up to the individual implementation.
xin your example has a known type and size at compile time, or inferable at runtime.free(ptr).