TIP: Click on subject to list as thread! ANSI
echo: c_plusplus
to: FRANK MASINGILL
from: CHRIS DOWNS
date: 1997-08-07 18:52:00
subject: Re: Ascertaining address

 FM> I found that I COULD bring up the addresses of elements of a
 FM> character array
 Yep.  And if you are using iostream, just cast the address to a
 void* and you can output the actual values of the addresses.
 FM> but then at the same time I tested something else I
 FM> had heard was true - that the external variables went on the heap
 FM> while the internal ones went on the stack.
 There are no requirements that variables be kept on the stack or on
 the heap or anywhere else.  There's not even a requirement that
 a system _have_ a stack or a heap.  But most commonly, local variables
 get storage on the stack.  Static variables (including globals) get
 stored in some memory location that has program length duration.
 Perhaps the system's startup code may call some OS routine to get
 a hunk of the system heap for static variables.  Perhaps not.
 It shouldn't matter as far as how you (or I!) write programs.
 FM> But I found that these
 FM> array element addresses were numbered downward just like the
 FM> addresses of my internal variables, declared within main().
 FM> What am I not seeing here?
 You're eyesight is excellent.  What you _are_seeing_ is implementation
 defined behavior!
 That automatic variables (local variables typically stored on the
 stack) can have increasing addresses comes from how the memory is
 allocated.  Local variables are not pushed onto the stack.  That
 could cause a heavy performance hit.
 Consider something like...
 void foo()
 {
   short i;
   char c;
   long j;
   DoSomething();
   return;
 }
 When this gets compiled, there is procedure entry code and proc exit
 code added.  (This is part of what is called "procedure call overhead".)
 The compiler knows how much space it needs for local variables.  So at
 proc entry, it can simply decrement from the stack pointer that many bytes.
 Then those bytes are "safe".  The compiler can then map the local vars
 to appropriate slots in that block of memory.  It could assign them
 from the old SP up or from the decremented SP down.  It doesn't matter.
 In fact, there's no guarantee that the memory space for one variable
 will directly follow the memory space for the preceedingly declared
 variable.  (Though there is a guranteed order for members in a
 struct.)
 Here's what you are guaranteed from a variable.  Let's use an
 array of chars for example.
 char buffer[2];
 You are guaranteed that you can safely dereference pointers to
 &buffer[0] and &buffer[1].  You can also safely get the address
 of one past the end of the array.  But you cannot safely dereference
 a pointer at one past the end, nor can you safely even get the
 address of more than one past the end or one from the beginning.
 Some of this is useless esoterica.  But then again, this concept is
 important for some situations like iterators in collection classes
 The STL uses this concept in it's begin() and end() members in the
 container classes.  end() returns "one past the end".
---
 þ Blue Wave/QWK v2.12 þ
---------------
* Origin: St. Louis Users Group (1:100/4)

SOURCE: echomail via exec-pc

Email questions or comments to sysop@ipingthereforeiam.com
All parts of this website painstakingly hand-crafted in the U.S.A.!
IPTIA BBS/MUD/Terminal/Game Server List, © 2025 IPTIA Consulting™.