Order of parameter / variables on stack in C Several years ago, I put together this little memory address exploration for my students to help them to understand pointers, arrays, the stack, and the heap.
I just compiled and ran it in a new environment (gcc on a AWS Linux server) and the order of the parameters for foo are different from what I would expect. The local function variables (d1 and e1) now have a higher address in comparison to the function parameters (a1, b1, and c1).
The addresses for the parameters / variables in function foo are listing as:

&amp;a1: fa2740fc
&amp;b1: fa2740f0
&amp;c1: fa2740e8
&amp;d1: fa27410c
&amp;e1: fa274100


Any thoughts on why variables d1 and e1 have higher addresses than a1, b1, and c1?
#include &lt;stdio.h&gt;
#include &lt;stdlib.h&gt;
#include &lt;string.h&gt;

int* foo (int a1, int b1[], int *c1)
{
  int d1 = *c1 + a1;
  int *e1;
  
  e1 = malloc (sizeof(int));

  printf (&quot;5) Addresses of arguments/variables of foo:\n&quot;);
  printf (&quot;   Update your stack sketch.\n&quot;);
  printf (&quot;     &amp;a1: %x\n&quot;, &amp;a1);
  printf (&quot;     &amp;b1: %x\n&quot;, &amp;b1);
  printf (&quot;     &amp;c1: %x\n&quot;, &amp;c1);
  printf (&quot;     &amp;d1: %x\n&quot;, &amp;d1);
  printf (&quot;     &amp;e1: %x\n\n&quot;, &amp;e1);

  printf (&quot;6) Values of arguments/variables in foo:\n&quot;);
  printf (&quot;   Include these on your stack sketch as well.\n&quot;);
  printf (&quot;     a1: %x\n&quot;, a1);
  printf (&quot;     b1: %x\n&quot;, b1);
  printf (&quot;     c1: %x\n&quot;, c1);
  printf (&quot;     d1: %x\n&quot;, d1);
  printf (&quot;     e1: %08x\n\n&quot;, e1);

  printf (&quot;7) *c1 == %x, why?  Explain using your stack drawing.\n\n&quot;, *c1); 
  
  printf (&quot;8) e1 is a reference to an integer, much like c1.  Why is e1 so\n &quot;);
  printf (&quot;   different in value?\n\n&quot;);

  return e1;
}


int main ()
{
  int a = 5;
  int b[] = {8, 14, -7, 128, 12};
  int c = 10;
  int d = 14;

  printf (&quot;1) Locations...\n&quot;);
  printf (&quot;   Use these locations to sketch the stack.\n&quot;);
  printf (&quot;     &amp;a: %x\n&quot;, &amp;a);
  printf (&quot;     &amp;b: %x\n&quot;, &amp;b);
  printf (&quot;     &amp;c: %x\n&quot;, &amp;c);
  printf (&quot;     &amp;d: %x\n\n&quot;, &amp;d);
  
  printf (&quot;2a) Values:\n&quot;);
  printf (&quot;   Why does b != 8?\n&quot;);
  printf (&quot;     a: %x\n&quot;, a);
  printf (&quot;     b: %x\n&quot;, b);
  printf (&quot;     c: %x\n&quot;, c);
  printf (&quot;     d: %x\n\n&quot;, d);

  printf (&quot;2b) Values:\n&quot;);
  printf (&quot;   What memory address is *b accessing?\n&quot;);
  printf (&quot;     *b: %x\n\n&quot;, *b);
  
  printf (&quot;3) Notice that the following increase by 4 each, why?\n&quot;);
  printf (&quot;     &amp;(b[0]): %x\n&quot;, &amp;(b[0]));
  printf (&quot;     &amp;(b[1]): %x\n&quot;, &amp;(b[1]));
  printf (&quot;     &amp;(b[2]): %x\n&quot;, &amp;(b[2]));
  printf (&quot;     &amp;(b[3]): %x\n\n&quot;, &amp;(b[3]));

  printf (&quot;4) Pointers can be added, but the addition might have interesting results.\n&quot;);
  printf (&quot;   Explain why b + 1 != b + 1 in the normal way of thinking about addition.\n&quot;);
  printf (&quot;     b:   %x\n&quot;, b);
  printf (&quot;     b+1: %x\n&quot;, b+1);
  printf (&quot;     b+2: %x\n&quot;, b+2);
  printf (&quot;     b+3: %x\n\n&quot;, b+3);
  
  foo (a, b, &amp;c);
}
I haven't delved into the details, but if a language doesn't define its own implementation (few do) then the implementation will vary depending on the architecture for which it is compiled. It will also vary over time as research provides hints and clues about efficiency (both compile time and run time efficiency).
So, one stack protocol might be appropriate for one architecture, but wildly inefficient on another, depending on the registers available for the stack as well as, perhaps, paging systems, and all the rest. So, the implementer will take advantage of whatever hardware is available on the machine of interest.
The normally thought of &quot;normal&quot; architecture (register-transfer) disappeared in the 60's or so. It is fun to think about and to simulate, but not especially realistic. C was designed originally for the PDP-7 architecture, which is pretty much obsolete.
Also, if a compiler uses some top-down techniques derived from LL processing as well as more &quot;normal for C&quot; bottom up processing, the parameters, in particular might wind up in a different order. For example, a compiler might use an intermediate language that is itself compiled and who can say what the characteristics of that intermediate language might be.
It doesn't affect your question, I think, but heap implementations might differ wildly between implementations.