6

I am using gcc version 4.7.2 on Ubuntu 12.10 x86_64.

First of all these are the sizes of data types on my terminal:

sizeof(char) = 1    

sizeof(short) = 2          sizeof(int) = 4
sizeof(long) = 8           sizeof(long long) = 8

sizeof(float) = 4          sizeof(double) = 8
sizeof(long double) = 16

Now please have a look at this code snippet:

int main(void)
{   
    char c = 'a';
    printf("&c = %p\n", &c);
    return 0;
}

If I am not wrong we can't predict anything about the address of c. But each time this program gives some random hex address ending in f. So the next available location will be some hex value ending in 0. I observed this pattern in case of other data types too. For an int value the address was some hex value ending in c. For double it was some random hex value ending in 8 and so on.

So I have 2 questions here.

1) Who is governing this kind of memory allocation ? Is it gcc or C standard ?

2) Whoever it is, Why it's so ? Why the variable is stored in such a way that next available memory location starts at a hex value ending in 0 ? Any specific benefit ?

Now please have a look at this code snippet:

int main(void)
{   
    double a = 10.2;
    int b = 20;
    char c = 30;
    short d = 40;

    printf("&a = %p\n", &a);
    printf("&b = %p\n", &b);
    printf("&c = %p\n", &c);
    printf("&d = %p\n", &d);

    return 0;
}

Now here what I observed is completely new for me. I thought the variable would get stored in the same order they are declared. But No! That's not the case. Here is the sample output of one of random run:

&a = 0x7fff8686a698
&b = 0x7fff8686a694
&c = 0x7fff8686a691
&d = 0x7fff8686a692

It seems that variables get sorted in increasing order of their sizes and then they are stored in the same sorted order but with maintaining the observation 1. i.e. the last variable (largest one) gets stored in such a way that the next available memory location is an hex value ending in 0.

Here are my questions:

3) Who is behind this ? Is it gcc or C standard ?

4) Why to waste the time in sorting the variables first and then allocating the memory instead of directly allocating the memory on 'first come first serve' basis ? Any specific benefit of this kind of sorting and then allocating memory ?

Now please have a look at this code snippet:

int main(void)
{   
    char array1[] = {1, 2};
    int array2[] = {1, 2, 3};

    printf("&array1[0] = %p\n", &array1[0]);
    printf("&array1[1] = %p\n\n", &array1[1]);

    printf("&array2[0] = %p\n", &array2[0]);
    printf("&array2[1] = %p\n", &array2[1]);
    printf("&array2[2] = %p\n", &array2[2]);

    return 0;
}

Now this is also shocking for me. What I observed is that the array is always stored at some random hex value ending in '0' if the elements of an array >= 2 and if elements < 2 then it gets memory location following observation 1.

So here are my questions:

5) Who is behind this storing an array at some random hex value ending at 0 thing ? Is it gcc or C standard ?

6) Now why to waste the memory ? I mean array2 could have been stored immediately after array1 (and hence array2 would have memory location ending at 2). But instead of that array2 is stored at next hex value ending at 0 thereby leaving 14 memory locations in between. Any specific benefits ?

rootkea
  • 1,474
  • 2
  • 12
  • 32
  • 2
    No "standard" are really involved. It may depend upon the version of the compiler used, the ABI, the kernel, the environment in which you run that program, etc. The ABI probably mandates that the stack pointer is 16 bytes aligned, and the compiler put the variables inside "as it wishes". And `array2` has to be word-aligned (multiple of 4 bytes) while `array1` don't need to be... – Basile Starynkevitch Apr 20 '13 at 14:54
  • 1
    Why are the room numbers on this side of the corridor all *even*? Why are the room numbers on the opposite side of the corridor all *odd*? – wildplasser Apr 20 '13 at 14:59
  • Why exactly do you ask? What is the reason behind your question, and why would you really care? (You should not code programs which depend so heavily on the exact reason of this). – Basile Starynkevitch Apr 20 '13 at 15:03
  • @BasileStarynkevitch - If compiler is behind all above 3 observations then there must be a reason why it's doing that. I mean it's really not a random thing to carefully sort variables and then storing them or always storing an array at some random hex value ending at `0`. There has to be some logic. Why the compiler is taking so much of pain? Please mention any specific benefits if you are aware of. – rootkea Apr 20 '13 at 15:16
  • @wildplasser - I think you didn't notice the hard work done by compiler or C standard implementation. Don't you think, carefully sorting the variables and then allocating the memory is totally different than randomly deciding the side of corridor which is going to have even room numbers ? – rootkea Apr 20 '13 at 15:21
  • Well the compiler is free to store your automatic variables in *any* order. In your case it appears to optimise for space (which *could* mean: occupying fewer cache slots) In any case: you should not worry. And you certainly should not rely on the order in this case. A different compilere (or a different version) can do things different if it wants to. – wildplasser Apr 20 '13 at 15:41
  • 1
    @rootkea: I still don't understand why you are asking the question, and why does it matter to you. This is typically part of the details you don't care about. Trust the compiler and the system, it should do things quite sensibly in practice. – Basile Starynkevitch Apr 20 '13 at 16:14
  • http://stackoverflow.com/questions/381244/purpose-of-memory-alignment – BlackBear Apr 20 '13 at 16:17

2 Answers2

7

The address at which the stack and the heap start is given to the process by the operating system. Everything else is decided by the compiler, using offsets that are known at compile time. Some of these things may follow an existing convention followed in your target architecture and some of these do not.

The C standard does not mandate anything regarding the order of the local variables inside the stack frame (as pointed out in a comment, it doesn't even mandate the use of a stack at all). The standard only bothers to define order when it comes to structs and, even then, it does not define specific offsets, only the fact that these offsets must be in increasing order. Usually, compilers try to align the variables in such a way that access to them takes as few CPU instructions as possible - and the standard permits that, without mandating it.

Theodoros Chatzigiannakis
  • 28,773
  • 8
  • 68
  • 104
  • So gcc is behind all the above 3 observations. Ok. So this answers question 1), 3) and 5). And compiler does this kind of allocation to reduce the fetching time. But this is quiet general statement. 1) I mean how exactly it helps the compiler if variables are sorted in increasing order of their sizes and then allocating the memory ? 2) How it reduces the fetching time or whatever benefit it supposed to do, if variables are stored in such a way that the next available memory location is some random hex value ending at `0` ? – rootkea Apr 20 '13 at 15:29
  • 2
    @rootkea - It happens that on your processor (x86) fetching data is fastest if the address is an even multiple of the data size. That way the info can travel straight ahead in the hardware without any possible delays needed to sort the bits out. For example, if your `double` is on an address ending in 4, the processor might have to read two 64-bit words and select four bytes from each read. That might take some extra time. – Bo Persson Apr 20 '13 at 15:54
  • The C standard does not dictate that automatic variables are allocated on a stack. In most cases they are, but they need not. – wildplasser Apr 20 '13 at 15:57
5

Part of the reasons are mandated by the application binary interface (ABI) specifications for your system & processor.

See the x86 calling conventions and the SVR4 x86-64 ABI supplement (I'm giving the URL of a recent copy; the latest original is surprisingly hard to find on the Web).

Within a given call frame, the compiler could place variables in arbitrary stack slots. It may try (when optimizing) to reorganize the stack at will, e.g. by decreasing alignment constraints. You should not worry about that.

A compiler try to put local variables on stack location with suitable alignment. See the alignof extension of GCC. Where exactly the compiler put these variables is not important, see my answer here. (If it is important to your code, you really should pack the variables in a single common local struct, since each compiler, version and optimization flags could do different things; so don't depend on that precise behavior of your particular compiler).

Community
  • 1
  • 1
Basile Starynkevitch
  • 223,805
  • 18
  • 296
  • 547