0
int main() { char a[3] = {1,2,3}; return sizeof(a); } 

Is a guaranteed to be in consecutive bytes in virtual memory? I know it may not be consecutive in physical memory as the mapping is done behind the scene by the MMU.

If the compiler notices i'm not taking the address of any of the elements, is it then free to put them on non consecutive addresses in memory or even put them in a register?

Let's assume the optimizer will not fully get rid of it in my example.

2
  • In the given case, it will be on the stack, and that is going to be quite active. If it were somehow to not be in consecutive memory, the OS would 100% have to make it appear as such to you or things would start breaking badly. Commented Jun 14, 2021 at 23:44
  • Does it have to be on the stack? if this was a regular integer it would definitely just be placed in a register (if not removed altogether). Commented Jun 14, 2021 at 23:46

4 Answers 4

5

Is a guaranteed to be in consecutive bytes in virtual memory? I know it may not be consecutive in physical memory as the mapping is done behind the scene by the MMU.

Your code is guaranteed to behave as-if the array was in consecutive bytes of address space.

If the compiler notices i'm not taking the address of any of the elements, is it then free to put them on non consecutive addresses in memory or even put them in a register?

It is free to do so even if you do take the address. The compiler can compile your code any way it wants to make it efficient so long as the code doesn't break.

Let's assume the optimizer will not fully get rid of it in my example.

Okay. But it's allowed to. C has an "as-if" rule which means that all rules are just about the behavior your code has to observe, they don't constrain how the compiler (or the machine) get that behavior.

Sign up to request clarification or add additional context in comments.

4 Comments

so I guess it could even put it all in a register, or random (allocable) addresses if it wanted to, as long as the code doesn't break ?
@Dan: That is correct. However, if you declare a with the keyword volatile, and you print the address of a (so that the address is observable), then the compiler's optimizer may actually be legally prevented from making any optimizations. I am not sure, though.
Thats right, volatile tells the compile to not optimize the variable.
@AndreasWenzel Nobody really knows. It's not clear what it means to take something that cannot, even in principle, be observed and declare it to be observable behavior. No modern compiler forces memory reads and writes in response to volatile, at least none that would be worth using on typical computers.
4

The non-pedantic answer is that, yes, for all intents and purposes, arrays are guaranteed to be stored contiguously in C. This is no accident, it's pretty much a fundamental part of the definition of an array.

The whole point of an array is that you can access any element in constant (that is, O(1)) time, notionally by computing an address, and without having to chase any links as you would with almost any other data structure. So if, as some obscure and invisible implementation detail, an array were somehow not actually stored contiguously, it would always have to act exactly as if it were stored contiguously. And since contiguity is the defining property of an array, I don't think there's any harm in thinking consciously about that property, and assuming that it's always true.

1 Comment

Plain-language works! Einstein was fond of saying that true genius was the ability to explain the complexities of nature to a child... The same holds true for C.
1

Well in this particular code snippet most likely a will be stored in the stack and yes in this particular case it would be contiguous.

However if you were to run at a higher optimization most likely any compiler would not even store a and just do constant propagation and just return the size of a.

If you were to allocate memory in heap then it depends on the allocator most likely if it is Buddy or slab allocator then more often than not they would be contiguous but if i were to have a naive free linked list allocator then it may not be contiguous when there are multiple calls for heap allocation. In case of Arrays this is not possible as you most likely will have single call so it would still be contigous.

Tools like objdump, opt from llvm, gdb etc are great tools if you want to check the disassembly and how the compiler lays out the assembly code across different optimization levels.

2 Comments

I don't understand your third paragraph. As far as I know, all allocators provide a program with a memory block on every request that it guaranteed to be contiguous. Only if a program makes two requests, then it is not guaranteed that the returned memory blocks are contiguous to each other, but the memory blocks are still guaranteed to be contiguous in themselves.
i see what you are saying, yes i meant if there were two requests more in the lines of when an application has more than one thread and calls malloc and lets say the allocator stores some metadata as well to help when it frees memory in case of naive linked list
1

C is defined in terms of an abstract machine. The bytes are guaranteed to be contiguous in the abstract machine.

The real machine can do literally anything so long as the observable behaviour of the program matches an allowed output of the program in the abstract machine.

So, there are no guarantees about any placement of data in the real machine.

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.