В вашем вопросе целая куча ошибочных предположений.
Вы предполагаете, что целочисленные аргументы передаются в стек сразу над адресом возврата (так как они находятся в многих - не всех - x86 ABI при вызове по умолчанию конвенции). Если бы это было так, то сразу после вызова ваш стек будет выглядеть так:
// stack frame of main( )
// ...
value of b
value of a
return address <--- stack pointer
Однако ваше предположение неверно. Вы скомпилировали свой код в 64-битный исполняемый файл (о чем свидетельствует размер указателя, который вы печатаете). Согласно OS X ABI, в 64-битном исполняемом файле Intel первые несколько целочисленных аргументов передаются в регистре, а не в стеке. Таким образом, сразу после вызова стек на самом деле выглядит так:
// stack frame of main( )
// ...
return address <--- stack pointer
Поскольку вы берете адреса a
и b
, они будут записаны в стек в некоторый момент перед вызовом printf( )
(если компилятор не является действительно умным и не реализует что ему на самом деле не нужно вручать printf( )
действительных указателей, потому что он не будет использовать указанное значение, но это будет довольно плохо с точки зрения оптимизации), но вы действительно не знаете, где они будут относительно обратный адрес; на самом деле, поскольку 64-битный ABI обеспечивает красную зону , вы даже не знаете, находятся ли они выше или ниже указателя стека. Таким образом, в то время, когда вы распечатываете адреса a и b, ваш стек выглядит так:
// stack frame of main( )
// ...
return address |
// ... |
// a and b are somewhere down here | <-- stack pointer points somewhere in here
// ... |
В общем, стандарт языка C ничего не говорит о макетах стека, или даже о том, что стек должен быть вообще . Вы не можете получить такую информацию каким-либо портативным способом из кода C.