home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: 10 Tools / 10-Tools.zip / snip9707.zip / CSTORAGE.TXT < prev    next >
Text File  |  1997-07-05  |  12KB  |  261 lines

  1. +++Date last modified: 05-Jul-1997
  2.  
  3.       A Brief Discussion of C Language Storage Modifiers
  4.       --------------------------------------------------
  5.   (a public domain tutorial by Carey Bloodworth & Bob Stout)
  6.  
  7.  
  8.  
  9. There  are  seven basic storage types:  auto, const, extern, global,
  10. register, static, and volatile.   Static  and  extern  can  also  be
  11. applied to functions.  (Although global is a basic storage class, it
  12. is not a keyword, like the other six.)
  13.  
  14. Put very simply:
  15.  
  16. auto: a normal stack variable declared and used within a function.
  17.  
  18. const:  it tells the compiler that you are not going to change  this
  19. variable  (that  it  is  'const'ant)  and  allows the compiler to do
  20. additional  type  checking  and  possibly  put  the  variable  in  a
  21. different  section of memory (such as ROM instead of RAM).  When the
  22. variable happens to  be  a  pointer,  the  pointer  itself, what the
  23. pointer points to, or both, can be declared constant.
  24.  
  25. extern:  it says the  variable  is  'extern'al  to the current file.
  26. You can use it in this module, but you have to actually  declare  it
  27. as global somewhere else.
  28.  
  29. global:  it is  declared  outside  of  any  function  and the entire
  30. program can 'see' the variable and modify it.
  31.  
  32. register:  used with a  local  /  auto  variable, it suggests to the
  33. compiler that it might be more efficient if it kept that variable in
  34. a CPU register.  The compiler is under no requirement to follow your
  35. suggestion.  If it doesn't follow your advice, the variable has  the
  36. same  storage  class  as  whatever it would normall have.  Trying to
  37. make a variable a 'register'  variable also prevents you from taking
  38. its address and using a pointer to it, since there is  obviously  no
  39. way to have a memory pointer point to a CPU register.
  40.  
  41. static:  Static has two meanings.  Inside a function, it  means  the
  42. variable  keeps its value between calls to that function.  When used
  43. with a variable or  function  that  would  other  wise be global, it
  44. tells the compiler that it is 'private' to that file.   Although  it
  45. is  'global'  to everything within that same file / module, no other
  46. file / module knows about it.
  47.  
  48. volatile:  This tells  the  compiler  not  to  keep  this value in a
  49. register, that the variable is 'volatile' and  can  change  on  it's
  50. own,  without  the  program  itself  doing  it.  The change could be
  51. caused by a multi-tasking program,  or  perhaps its the clock timer,
  52. or some other  situation  where  the  compiler  must  not  make  any
  53. assumptions about what the value is.
  54.  
  55. Here is an example program:
  56.  
  57. int Global1;
  58. int Global2=10;
  59. const int CVar=13;
  60. const int *Ptr1;
  61. int * const Ptr2=&Global1;
  62. const int * const Ptr3=&Global2;
  63. long volatile * const Clock=some address;
  64. extern int errno;
  65.  
  66. void Func1(void)
  67. { int Local1;
  68.   int Local2=5;
  69.   static int Local3=10;
  70.  
  71. Local1=17;
  72.  
  73. /* do stuff */
  74.  
  75. if (errno != 0 )
  76.   {int Local4;
  77.    Local4 = func2();
  78.    /* do something with Local4 */
  79.   }
  80.  
  81. Local1=Local1-1; /* useless */
  82. Local2=Local2-1; /* useless */
  83. Local3=Local3-1; /* purposeful */
  84. }
  85.  
  86.  
  87. Auto class
  88. ==========
  89.  
  90. An 'auto' variable is just a normal variable declared within a  pair
  91. of braces { }.  Generally, that would be normal variable declaration
  92. at the beginning of a regular function, but  it  can  also  be  done
  93. within the function itself, if a temp variable is needed in just one
  94. place, etc.  The term 'auto' is rarely used these days, because it's
  95. understood  that  a  local variable will be 'auto' unless you say to
  96. make it static.
  97.  
  98.  
  99. Examine the sample program  above.   The variables Local1 and Local2
  100. are local / auto  variables  and  can  be  used anywhere in Func1().
  101. Local4 is also a local / auto variable, but  it  can  only  be  used
  102. within  that  inner  set  of  brackets.
  103.  
  104. Auto / local variables are put on the stack.  They  just  'suddenly'
  105. appear  when  you  enter  a  function,  and  unless  you  explicitly
  106. initialize the variable, its  contents  will be pure random garbage.
  107. Above,  Local1  is  unitialized.   Its  value  is unknown because it
  108. depends on whatever value happens to already be on the stack at that
  109. point.   Unlike  global  variables,   an   auto  variable  is  _not_
  110. automatically initialized to zero.  Auto variables will have garbage
  111. in them  unless  you  explicitly  initialize  them,  either  in  the
  112. declaration  itself  (like with Local2) or explicitly in the program
  113. (like with Local1).
  114.  
  115.  
  116. Const class
  117. ===========
  118.  
  119. A  constant variable is one that you are promising (and the compiler
  120. should be  enforcing)  that  it  will  not  change.   This  lets the
  121. compiler make certain optimizations,  and  enforce  a  bit  of  type
  122. checking, etc.  CVar is being initially  set to 13, and it will, for
  123. the rest of the program, have that value.   You  may  initialize  it
  124. when you declare it, but that is the only time it may be set.
  125.  
  126. When   the   variable  is  a  pointer,  things  become  a  bit  more
  127. complicated.  For example, Ptr1 is a pointer to an integer constant.
  128. That means that although the pointer  can change, you can not change
  129. the value of what the pointer points to.  That can  be  useful  when
  130. you are using the pointer  to  reference a pre-calculated data table
  131. and you want to be reasonably sure of not modifying it.
  132.  
  133. On  the other hand Ptr2 itself can not be modified, although what it
  134. points to can.   It  can  only  point  to  one address, although the
  135. contents of that address can change.  This has  limited  usefulness,
  136. although  it  does  let you set up 'aliases' for another variable or
  137. address.
  138.  
  139. The  third  type,  Ptr3, is a combination of both.  The value of the
  140. pointer  can  not  be  changed  after  being  initialized  when it's
  141. declared, nor can what it points to be changed.   As  you  can't  do
  142. anything with a pointer like this, it's fairly useless.
  143.  
  144.  
  145. Note that using 'const' is just  a compiler / language safety check.
  146. It does not actually prevent you from doing it with  other  methods,
  147. such  as  by  type  casting  the  'const'  away,  or with some other
  148. pointer, etc.  As  always,  C  will  let  you  do anything you like,
  149. provided you are reasonably sure you want to do it.
  150.  
  151.  
  152. And finally, the 'const' is a bit different in C++.  In that case, a
  153. const variable can sometimes behave as if you had used a #define  to
  154. set  it  at  that  value.   In  C,  a 'const' value will always take
  155. storage, but with C++, if the compiler notices you are only using it
  156. a certain way, it  can  just  go  ahead  and  use the value of const
  157. variable, without ever really creating the variable.
  158.  
  159.  
  160. Extern class
  161. ============
  162.  
  163. Declaring something is 'extern' just means that you are not actually
  164. defining  it  at  this  point, that it's done somewhere else, usally
  165. some other program module.  The extern declaration does not actually
  166. consume any storage (for a  variable)  or generate any function code
  167. (if it's a function), it just lets the compiler know that it  really
  168. does exist, but just not here.
  169.  
  170. In the example above, we are declaring the variable  'errno'  as  an
  171. external  integer.   (This  is  rather  bad  form to do it with this
  172. particular variable, because  that  is  C's error reporting variable
  173. and it's really declared in the standard library header  <stdlib.h>,
  174. but I wanted to show something you might recognise.)
  175.  
  176. This means that the actual declaration (which actually allocates the
  177. memory  for the global variable) is in some other file (or even in a
  178. library that you will link in), but that we can _use_ it.
  179.  
  180. Declaring functions as  'extern'  is  similar.
  181.  
  182. If you look through your library header files, such as <stdlib.h> or
  183. <stdio.h> you  will  see  many  examples  of  extern  functions  and
  184. variables.   They  are  actually defined elsewhere, and put into the
  185. precompiled libraries, but you can use them just as if they actually
  186. existed in your file.
  187.  
  188.  
  189. Register class
  190. ==============
  191.  
  192. A  register  variable  is  just your hinting to the compiler that it
  193. might be more efficient if the compiler kept that simple variable in
  194. a CPU register.  It also  prevents  the  compiler from being able to
  195. take the address of  that  variable,  meaning  you  can't  have  any
  196. pointers  to  that  variable,  since it doesn't make sense to have a
  197. memory pointer trying  to  point  to  a  CPU register, which doesn't
  198. exist in memory.  Only local, auto variables can be 'register'.
  199.  
  200.  
  201. Static class
  202. ============
  203.  
  204. Static has two meanings.  The first is towards local  variables  and
  205. the second is towards external, non-local identifiers (variables and
  206. functions.) 
  207.  
  208. A local variable can also  be  declared  as 'static', as well as the
  209. implicit or explict declaring of 'auto'.  This is a cross between  a
  210. global  variable  and  a  local  auto  variable.   Like  all  global
  211. variables, when the  program  is  first  run,  it  is  automatically
  212. initialized to 0  if  you  don't  explicitly initialize it yourself.
  213. The only real difference is that a static local var  is  known  only
  214. within  that  function  it  is  defined.  Its value is not destroyed
  215. between calls to that  function.   The  variable Local3 is initially
  216. being set to 10; And what  ever  I  do  to  that  variable  will  be
  217. remembered  between  calls  to  it.   For example, at the end of the
  218. function, right before I  leave,  I  am decrementing Local1, Local2,
  219. and Local3.  Because Local1 and Local2 are normal auto variables, it
  220. doesn't matter because the next time I call  Func1(),  their  values
  221. will   be   undetermined  until  they  are  explicitly  initialized.
  222. However, the variable Local3 is declared as 'static'.  That means it
  223. _will_ remember its contents between  calls.  The first time I call,
  224. it is initialized to what I set it (or initialized to 0 by  default,
  225. like  global  variables  are).   The second time I call Func1(), the
  226. value will _not_ be reinitialized.  It  will retain the value it had
  227. when I  left  the  function  before.   In  this  case,  it  will  be
  228. decremented by one with each call.
  229.  
  230. When you use 'static' outside  of  a  function,  it  behaves  a  bit
  231. differently.   It  means  that  whatever  you  use  it on (whether a
  232. variable or a function) will not  be  visible outside of that file /
  233. module you are using  it  in.   This  lets  you  enforce  a  bit  of
  234. 'locality of usage'  in  your  programming.   If  you  have a set of
  235. related variables and functions, and you keep them in a single file,
  236. and  feel  that only the functions in that file itself should modify
  237. those variables or call those  functions,  then you can declare them
  238. as 'static' to hide them from the rest of the program.
  239.  
  240.  
  241. Volatile class
  242. ==============
  243.  
  244. You can also declare a  variable  to  be 'volatile'.  That just lets
  245. the compiler know that the value of the variable will change due  to
  246. outside influences.  It might be the clock counter, or some hardware
  247. port  accessed  via  a  fixed memory location, or whatever.  It just
  248. tells the compiler not to take any short cuts and to not keep it  in
  249. a  register.   Every  time  you use that variable, the compiler will
  250. actually reference that variable  or  location, rather than using an
  251. older value from a previous access.
  252.  
  253. In the program example above, I am declaring a pointer  to  be  both
  254. const  and  volatile.   The  pointer itself is constant, it will not
  255. change from that address of  where  the  clock is located.  Its also
  256. declared  as volatile, meaning that the value of what the pointer is
  257. always point to will change outside of the program's operation.  So,
  258. every time I do  *clock,  the  compiler  has to always generate code
  259. that reads that memory address.  If I did  twoclock=*clock + *clock;
  260. the compiler would have to generate two seperate reads to the clock.
  261.