Velocity Reviews - Computer Hardware Reviews

Velocity Reviews > Newsgroups > Programming > C Programming > Variables allocated on stack

Reply
Thread Tools

Variables allocated on stack

 
 
Bogdan
Guest
Posts: n/a
 
      11-24-2011
Hi

I had during an interview this question: which variables are
allocated on the stack in a function ? I am unsure how the output
variable is handled. Is this one too allocated on the stack and popped
when the function exists ?
Here is an example:

char* some_function(char c)
{
char *out = malloc(10);
return out;
}

On the local stack are there one char and 2 pointers to chars ?

Bogdan
 
Reply With Quote
 
 
 
 
Ian Collins
Guest
Posts: n/a
 
      11-24-2011
On 11/25/11 10:28 AM, Bogdan wrote:
> Hi
>
> I had during an interview this question: which variables are
> allocated on the stack in a function ? I am unsure how the output
> variable is handled. Is this one too allocated on the stack and popped
> when the function exists ?
> Here is an example:
>
> char* some_function(char c)
> {
> char *out = malloc(10);
> return out;
> }
>
> On the local stack are there one char and 2 pointers to chars ?


The question was bogus, either trick or the interviewer had a rather
myopic viewpoint.

There isn't a correct answer. On some machines (that do have a stack),
nothing will be on the stack. Both an and out will be in registers.

Then there machines that don't have a stack....

--
Ian Collins
 
Reply With Quote
 
 
 
 
jacob navia
Guest
Posts: n/a
 
      11-24-2011
Le 24/11/11 22:28, Bogdan a écrit :
> Hi
>
> I had during an interview this question: which variables are
> allocated on the stack in a function ? I am unsure how the output
> variable is handled. Is this one too allocated on the stack and popped
> when the function exists ?
> Here is an example:
>
> char* some_function(char c)
> {
> char *out = malloc(10);
> return out;
> }
>
> On the local stack are there one char and 2 pointers to chars ?
>
> Bogdan


Conceptually a function has a stack that holds argument's values
and local variables. In your example the "c" argument and the
"out" pointer are in that stack.

The return value is normally in a register but it can be also
be understood as a stack.

In your example, a register would hold the value of the "out" pointer
after the execution of the function.

Today in a normal x86 based PC (linux, macintosh or windows) the first
parts of the execution stack are held in register, which one variying
with the calling conventions of the operating systems in question.

Under windows, the first 4 arguments are held in registers, under linux
or macintosh the first 7 arguments go into registers, when possible.

Do not forget that some arguments never go into registers because
they are too big for them. For instance, when you have a 476 byte
structure and you pass it by value the value goes into the stack
even if maybe the first 128 bytes would fit into a series of registers.

Depending on the specific machine architecture, some types have a
preferred set of registers where they are passed to functions, instead
of the general purpose registers. Specifically double/long double values
go into the xmm or the FPU registers (in a x86 CPU) or into the FP unit
(Power PC) etc.

What needs to be retained is that C implies (because it accepts
recursive functions) a stack like organization of the activation frames
of each function.

 
Reply With Quote
 
Jens Thoms Toerring
Guest
Posts: n/a
 
      11-24-2011
Bogdan <(E-Mail Removed)> wrote:
> I had during an interview this question: which variables are
> allocated on the stack in a function ? I am unsure how the output
> variable is handled. Is this one too allocated on the stack and popped
> when the function exists ?
> Here is an example:


> char* some_function(char c)
> {
> char *out = malloc(10);
> return out;
> }


> On the local stack are there one char and 2 pointers to chars ?


This can actually be a clever question, at least if it's meant
to test your understanding on several levels (assuming that the
person asking it is aware of that).

The correct answer to the question (unless further qualified)
is, of course, that it's impossible answer it. The C standard
doesn't mandate the existence of a "stack", "heap" etc. (none
of these words appear in the standard at all). It is left to
the discretion of the compiler where it gets the memory needed
from.

On the other hand on all machines I am familiar with compilers
use a stack and a heap. And (non-static) local variables like
'out' are allocated (if necessary) on the stack (while alloca-
tions with malloc() are made from the heap).

Things get even more interesting since there is a chance
that a local variable actually might not reside in memory at
all, e.g. in this function the compiler (at least when allowed
to do a bit of optimization) might rather likely not need room
on the stack for 'out' but will be able to get along with a CPU
register - the function could easily rewritten as

char * some_function( char c )
{
return malloc( 10 );
}

and then there's no 'out' variable left.

The next question is how values are passed between the caller
and the function. In the simplest case (again, on machines one
typically encounters - remember that there is no requirement
that a stack exists at all) arguments and return values are
put on the stack. But if there aren't too many of them the
compilers often passes them in CPU registers. Thus for the
function there is a good chance that neither 'c' nor 'out'
ever make it to the stack and instead just reside in CPU
registers (which, again, might depend on the settings for
the compiler, gooogle for e.g. "calling convention").

So, except for the first statement that the question, can't
be answered, it all depends on how the compiler works (and
the architecture the program is compiler for). It only can
be determined for sure by inspecting the assembler code the
compiler generates. But that, of course, is then not a
question about C but about the way a certain compiler im-
plements what is required by the C standard (though it's
also an interesting question that a compentent C programmer
is not unlikely to at least have spend a bit of time won-
dering about).
Regards, Jens
--
\ Jens Thoms Toerring ___ http://www.velocityreviews.com/forums/(E-Mail Removed)
\__________________________ http://toerring.de
 
Reply With Quote
 
Malcolm McLean
Guest
Posts: n/a
 
      11-25-2011
On Nov 24, 11:28*pm, Bogdan <(E-Mail Removed)> wrote:
> Hi
>
> *I had during an interview this question: which variables are
> allocated on the stack in a function ? I am unsure how the output
> variable is handled. Is this one too allocated on the stack and popped
> when the function exists ?
> Here is an example:
>
> char* some_function(char c)
> {
> * * *char *out = malloc(10);
> * * *return out;
>
> }
>
> On the local stack are there one char and 2 pointers to chars ?
>

A modern compiler would probably just optimise that function to a call
to malloc().

However the abstract C compiler needs a stack for the function calls,
and a stack for variables. When you call a function, the address of
the instruction to return to in caller is pushed onto the call stack.
Then the parameters are pushed onto the variable stack (in this case,
c). Then the local variables are pushed onto the variable stack (in
this case, out). The function then does its calculations, the variable
stack is popped, the return address is popped off the call stack and
the function returns. So what happens to the return value? Almost
always, it is returned in a register.

However pushing and popping stacks is not very efficient. So compilers
use registers as much as possible. On most processors, the first four
parameters will be passed in registers. Also, the call stack can be
the same as the variable stack.
--
New: sequence logo generator
http://www.maclommclean.site11.com/www

 
Reply With Quote
 
BartC
Guest
Posts: n/a
 
      11-25-2011
"Malcolm McLean" <(E-Mail Removed)> wrote in message
news:(E-Mail Removed)...
> On Nov 24, 11:28 pm, Bogdan <(E-Mail Removed)> wrote:


>> char* some_function(char c)
>> {
>> char *out = malloc(10);
>> return out;
>>
>> }
>>
>> On the local stack are there one char and 2 pointers to chars ?
>>

> A modern compiler would probably just optimise that function to a call
> to malloc().
>
> However the abstract C compiler needs a stack for the function calls,
> and a stack for variables. When you call a function, the address of
> the instruction to return to in caller is pushed onto the call stack.
> Then the parameters are pushed onto the variable stack (in this case,
> c). Then the local variables are pushed onto the variable stack (in
> this case, out). The function then does its calculations, the variable
> stack is popped, the return address is popped off the call stack and
> the function returns. So what happens to the return value? Almost
> always, it is returned in a register.


If you're going to talk about abstract call and variable stacks, then why
not put the return value onto the abstract variable stack too?

> However pushing and popping stacks is not very efficient. So compilers
> use registers as much as possible. On most processors, the first four
> parameters will be passed in registers.


That's fine until the registers are needed for something else or you need to
make another function call. Then they need to be saved, perhaps by pushing
onto the stack, then popping again. Except this might be done a million
times within the function, instead of just once.

> Also, the call stack can be
> the same as the variable stack.


Some compilers have an option to display the code they generate. Then it is
possible to see some actual code.

--
Bartc

 
Reply With Quote
 
jacob navia
Guest
Posts: n/a
 
      11-25-2011
Le 25/11/11 12:05, BartC a écrit :
>> However pushing and popping stacks is not very efficient. So compilers
>> use registers as much as possible. On most processors, the first four
>> parameters will be passed in registers.

>
> That's fine until the registers are needed for something else or you
> need to make another function call. Then they need to be saved, perhaps
> by pushing onto the stack, then popping again. Except this might be done
> a million times within the function, instead of just once.
>


Unlikely. In most cases the compiler knows if the function calls
another function and will save the registers at the start
in the function prologue...


 
Reply With Quote
 
BartC
Guest
Posts: n/a
 
      11-25-2011


"jacob navia" <(E-Mail Removed)> wrote in message
news:jant5d$lji$(E-Mail Removed)...
> Le 25/11/11 12:05, BartC a écrit :
>>> However pushing and popping stacks is not very efficient. So compilers
>>> use registers as much as possible. On most processors, the first four
>>> parameters will be passed in registers.

>>
>> That's fine until the registers are needed for something else or you
>> need to make another function call. Then they need to be saved, perhaps
>> by pushing onto the stack, then popping again. Except this might be done
>> a million times within the function, instead of just once.
>>

>
> Unlikely. In most cases the compiler knows if the function calls
> another function and will save the registers at the start
> in the function prologue...


Fair enough. In that case it's just another way to push those parameters,
via registers, leaving it to the callee to do the actual pushing. With the
advantage that the callee will know when it is possible to avoid pushing
onto the stack.

The disadvantage for the caller might be a little more effort, for the
compiler, in evaluating complex parameters and ensuring those registers
already loaded are preserved. For example:

fn(f(p,q,r), g(s), h(t,u,v), i());

Here, purely stack-based parameters would be far simpler.

--
Bartc

 
Reply With Quote
 
jacob navia
Guest
Posts: n/a
 
      11-25-2011
Le 25/11/11 12:40, BartC a écrit :
>
>
> "jacob navia" <(E-Mail Removed)> wrote in message
>> Unlikely. In most cases the compiler knows if the function calls
>> another function and will save the registers at the start
>> in the function prologue...

>
> Fair enough. In that case it's just another way to push those
> parameters, via registers, leaving it to the callee to do the actual
> pushing. With the advantage that the callee will know when it is
> possible to avoid pushing onto the stack.
>
> The disadvantage for the caller might be a little more effort, for the
> compiler, in evaluating complex parameters and ensuring those registers
> already loaded are preserved. For example:
>
> fn(f(p,q,r), g(s), h(t,u,v), i());
>
> Here, purely stack-based parameters would be far simpler.
>


Yes, I agree with you 100%. Having implemented linux's calling
conventions where you have nothing less than 7 registers that
can receive parameters those calls with embedded cals in the arguments
evaluation are a plain nightmare...

For me.

But in the big view where the compiler writer is just a matter of
fact that nobody cares about, this speeds up the code in MOST cases,
what is the important point anyway.
 
Reply With Quote
 
Seebs
Guest
Posts: n/a
 
      11-26-2011
On 2011-11-25, BartC <(E-Mail Removed)> wrote:
> Fair enough. In that case it's just another way to push those parameters,
> via registers, leaving it to the callee to do the actual pushing. With the
> advantage that the callee will know when it is possible to avoid pushing
> onto the stack.


Yes.

> The disadvantage for the caller might be a little more effort, for the
> compiler, in evaluating complex parameters and ensuring those registers
> already loaded are preserved. For example:


> fn(f(p,q,r), g(s), h(t,u,v), i());


> Here, purely stack-based parameters would be far simpler.


Right.

But you don't always get a vote -- the ABI may have specified the rules
for you. And in fact, often has.

-s
--
Copyright 2011, all wrongs reversed. Peter Seebach / (E-Mail Removed)
http://www.seebs.net/log/ <-- lawsuits, religion, and funny pictures
http://en.wikipedia.org/wiki/Fair_Game_(Scientology) <-- get educated!
I am not speaking for my employer, although they do rent some of my opinions.
 
Reply With Quote
 
 
 
Reply

Thread Tools

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is On
HTML code is Off
Trackbacks are On
Pingbacks are On
Refbacks are Off


Similar Threads
Thread Thread Starter Forum Replies Last Post
C/C++ compilers have one stack for local variables and return addresses and then another stack for array allocations on the stack. Casey Hawthorne C Programming 3 11-01-2009 08:23 PM
stack frame size on linux/solaris of a running application stack Surinder Singh C Programming 1 12-20-2007 01:16 PM
perl variables allocated in shared memory - feasible/possible/done already? Chris Perl Misc 1 02-03-2007 06:12 PM
variable allocated from stack/bss ?? onkar C Programming 148 12-18-2006 07:22 AM
Dynamically Allocated Memory vs. Statically allocated Memory csnerd@gmail.com C++ 5 12-09-2004 01:44 AM



Advertisments