Initializing arrays

cancel
Showing results for 
Show  only  | Search instead for 
Did you mean: 

Initializing arrays

3,727 Views
UtopiaTim
Contributor III
Hi all,
 
A program that I am working on uses a number of arrays to hold various
items such as time, date, etc.
 
Out of reset, I would like these to be pre-loaded with data which is valid.
 
In reading some information, it is suggested that the following code will
initialize those arrays:
 
static int number[3] = { 5, 7, 2 };
 
however, when I put this in and compile it, I don't see any code that
actually takes the data and puts it into the ram array.
 
Another method that I have tried is placing the following into a
function.  Bear in mind that I have about 400 bytes (in 56 arrays)
 
Time1_day1[0]=0x01;
Time2_day1[1]=0x01;
Time3_day1[2]=0x07;
Time4_day1[3]=0x01;
Time5_day1[4]=0x01;
Time6_day1[5]=0x01;
Time7_day1[6]=0x01;
Time8_day1[7]=0x01;
 
This works fine up until the 39th line (trying to do it brute force),
then I get an error message.
 
Back to the original question:  Is there an easy to initialize an
array with values?
 
Thanks,

Tim
Labels (1)
0 Kudos
15 Replies

1,338 Views
allawtterb
Contributor IV
The first method should work fine, the reason you might not see it actually being copied into these locations is it is probably being copied in the startup code.
0 Kudos

1,338 Views
UtopiaTim
Contributor III
Hi Allawtterb,
 
I looked into all the code, & didn't see any code (or data tables) that
would run & put the values into Ram at startup.
 
Thanks,
 
Tim
0 Kudos

1,338 Views
JimDon
Senior Contributor III
Thats because you didn't do anything with them.
The compiler optimized away the initialization since you didn't use the values in the array.


If you did this, then the array would be filled in:

Code:
static int number[3] = { 5, 7, 2 }; // 100% correct syntax.
  volatile int a;   int i;   for ( i = 0 ;i < 3  ;++i)      a = numbers[i];

// also this works, if you don't feel like counting
int numbers[]={1,2,3};
// if you need to know how many are in it:
int a = sizeof(numbers)/sizeof(int);
// this is calculated at compile time.
// Just wondering, why did you use static? (a quiz)

 You want the smallest code possible so don't fault the compiler for saving ram you don't need (because you never used it!)








Message Edited by JimDon on 2008-01-23 03:39 PM

Message Edited by JimDon on 2008-01-23 03:41 PM
0 Kudos

1,338 Views
UtopiaTim
Contributor III
Hi Jim,
 
Thanks.  Plugged the code in (removed the -s- from number),
               but got a C2801 '}' missing.  All braces are in the right
               places. Moved the 'static int xxxxx; to outside the function,
               but kept the rest of the routine inside the funct.
 
I thought that by merely adding the values to the end of the
line, it would automatically load the values, as opposed to the
general case of:  static int number[3]; which would just reserve
the three locations.
 
Do I need to do one of these little routine for each of the arrays?  That's
a lot of code to run (56 separate arrays).
 
What if I just wanted to load all the arrays with the same value (non-zero)?
 
- Static -
Since I placed the array definitions within a function (main.c here), I wanted
other functions to be able to use them.  However, in the final form, I will probably
put all the arrays with the other variables, and change them to unsigned char.
 
Tim
0 Kudos

1,338 Views
JimDon
Senior Contributor III
No the routine is just to trick the compiler thinking you are using it.
Once you add code that really does use it, it will be there.

The other array set up should be outdie the function.
Onve you have a line of code in a function you can not declare anymore variables:

f()
{
    int i;
i = 2;
int a; // error, can't declare after code...
}
If you are still getting an error, show me. It's quit hard to tell from the message form the compiler.

You can't awlays take what the error says at face value - also, many times fixing the first error will fix or change later errors. It has to do with the particlar way "C" grammer is. It is called "context free" and once the parser gets tripped up by a syntax error it is hard for it figure out what you meant.
So for now just fix the first error. Of course if you notice that you have made othere errors,then fix those too.
Also, if you click on those icon in the upper right corner, you shut off the warning and get to the errors faster. Some warnings this compiler issues are silly sounding, but quite often it could mean something wrong.

0 Kudos

1,338 Views
UtopiaTim
Contributor III
Hi Jim,
 
Hmmm,  still having a bit of a problem.  Got it to compile, but it
doesn't init the values.  It blows up when enters into the for loop.
Here's the code: 
 
void Initialize_variables(void);
//*************************
//    init variables
//*************************
void Initialize_variables(void){
static int number[3] = {1,2,3};      
volatile int a;
 int i;
 for (i = 0 ;i < 3 ;++i)
    a = number[i];
}
 
if I use:
 
unsigned char number[3] = {1,2,3};
 
(without any code), then it fills below
the stack.  If I put a bunch of the arrays
into the code, then the arrays will bump
into the machine registers, giving me a
read error.
 
Not sure how to make it put the arrays above
the stack.  Anyhow, think the static is the one
I want, because I need to manipulate the arrays
from other functions.
 
Thanks,

tim
 

  
0 Kudos

1,338 Views
JimDon
Senior Contributor III
Code:
// This code works fine.// Did you call the function and step into it?
// If you never call the function, then the compiler won't bother
// putting any if there.
 void Initialize_variables(void){static int number[3] = {1,2,3};      volatile int a; int i; for (i = 0 ;i < 3 ;++i)    a = number[i];}

 
"unsigned char number[3] = {1,2,3};
 (without any code), then it fills below
the stack. "
Which again is 100% correct. Typically, the stack is placed at the top of ram and grows down.
You can control the stack placement in the prm file.
"If I put a bunch of the arrays
into the code, then the arrays will bump
into the machine registers, giving me a
read error."
I don't remember what chip you are using. Either you've run out of memory, you used tiny model or we need to adjust your prm file. Post your prm file please.

Now the meaning of static. unfortunately the meaning of the key word static in C and C++ changes depending on how you use it. One thing very different from asm language is the concept of scoping.
variables and other items have an attribute referred to as scope, and it means who can "see" the variable.

There are three basic scopes: program, file and function.
As you know variables defined in a function can only be seen with in that function. This is function scope. Normally variable defined outside of a function have program scope, meaning and file that is linked in could see it as well as all the code in the file where it is declared.
If you declare a variable outside of a function static, that limits it's scope to only that file.
This is done to make variable private to that file.



Code:
// The first meaning of static - limiting scope.static int a;  // only code in this file can see 'a'int b;         // any file linked into this program and see b.void (void){ // example of funcction scope.  int c; // only code in this function and see 'c'}

The second meaning of static is within a function. Normally  variables declared in a function are "automatic" this means they are created on the stack and go away when you leave the function.
When you declare a variable static in a function, it is no longer on the stack and is placed in ram or rom and retains it's value across function calls. However, it's scope is still for that function only.
You can however return a pointer to it so other code could see it.

Code:
int*  f(void){   int a=0; // created on the static. goes away when I leave this function.   static int b=0; // created in ram - keeps it's value.   a = 1;    // The next time I  call the function, a will be 0
   b = 1;    // b will still be 1.
  return &b; // ok - lets the caller see b.  return &a; // error - this would be a terrible mistake
             // and will result in a crash or other odd bugs.
(you wouldn't really have two returns, just for illustration)

}

 










0 Kudos

1,338 Views
allawtterb
Contributor IV
Good post JimDon


JimDon wrote:
The second meaning of static is within a function. Normally  variables declared in a function are "automatic" this means they are created on the stack and go away when you leave the function.
When you declare a variable static in a function, it is no longer on the stack and is placed in ram or rom and retains it's value across function calls. However, it's scope is still for that function only.
You can however return a pointer to it so other code could see it.

Sometimes this is referred to as Storage Duration and there was a recent article on embedded.com talking about Scope and Storage Duration.  The link is below and the article discusses C and C++.  It is the second part of a disucssion on Scope, the first part is linked as well.
Part 1:
Part 2:
 

 
0 Kudos

1,338 Views
JimDon
Senior Contributor III
Thanks for the corrections an compliments.
Needless to say I have have a real job too and and do this rather quickly, sometimes to my regret and embarrassment.

Scope implies storage duration, but of course are not exactly the same. In the function f() above 'a' and 'b' have the same scope but different storage durations. I guess you could say that static overrides the storage duration in a function.

Just for the sake of completeness, in c++ static has yet a third meaning.
- If you declare a member variable static in a class, it means that for all instances of the class there is one and only one copy of the member variable.
- if you declare a function static, it means that the function is not associated with an instance of the class and can be called with out instantiating an instance. Basically it is just a "C" function that is scoped in a class.
Quite handy for call backs (like a window hander) or a utility class.
When I was learning c++ this thru me off, as I thought I already knew what it meant.

If you don't use c++ feel free to ignore.





Message Edited by JimDon on 2008-01-24 01:40 PM
0 Kudos

1,338 Views
J2MEJediMaster
Specialist I
Jim:

A really good explanation there on the use of static. I have only one minor quibble, and it has nothing to do with your fine description. It's more of a typo. In your last code example, the line:

Code:
int a=0; // created on the static. goes away when I leave this function.

Should be:
 
Code:
int a=0; // created on the *stack*. goes away when I leave this function.

 As it is, that comment might create some confusion. Hope this helps,

---Tom

0 Kudos

1,338 Views
bigmac
Specialist III
Hello Tim,
 
When you first created your CW project, did you specifically select the option to provide ANSI initialization code?  My understanding is that, unless you do this, the startup code created does not initialize the global and static variables.  The initialization of each variable will default to zero, unless you provide explicit values within the variable definition.
 
If you require variables to be accessible from more than one function, they should be global variables.  Static variables may, or may not, be accessible, depending on where they are defined.
 
You will need to become familiar with the PRM file, used by the linker, in order to control where different variables are placed.  Conventionally, the global and static variables should start at a low RAM address, and work upward, and the stack should start at top of RAM (and will work downward).  The total RAM available for the device, will usually determine whether the globals should commence within page zero RAM, or this RAM is reserved for special variable that will benefit from the faster access, and more compact code provided by page zero access.
 
Regards,
Mac
 
0 Kudos

1,338 Views
UtopiaTim
Contributor III
Hi Mac,
 
I had sat down to build a small program to do some array testing, and I saw that when
I created the project.
 
I was going to send Jim a note to that effect - thanks!!!  It's pretty obvious why things are
doing what they are (stack/array allocation, etc).
 
Thanks again,
 
Tim
0 Kudos

1,338 Views
Lundin
Senior Contributor IV
Some further information:

Every variable allocated at file scope (globals) are of static storage duration. It doesn't matter if they have the keyword static in front of them or not. Though if you declare a local variable as static, it will of course get static storage duration as well.

All such variables will live throughout the whole execution of the program. ISO C requires that they are initialized to a value before program startup. If the programmer did this explicitly, as in the original post, they will be set to the values written by the programmer. If the programmer didn't initialize them explicitly, they will -still- be initialized, to zero.

In order for Codewarrior to conform with ISO C, they will need to add the file startup08.c to "copy-down" values to all variables with static storage duration. They also set the stack from there, to avoid complications of ignorant users doing this themselves in the wrong way.

There are however some problems with the copy-down process at startup:

First of all, C was designed for RAM-based Unix systems in office environments. They pretty much assumed that the program was stored in RAM and that there was an OS in the system. Nowadays C has a much wider usage, and there won't necessarily be an OS in the system. This means that some part of the program must run before main() is started (or if you will, before the ISO C-conformant part of the program is started).

One problem is that the copy-down code will add plenty of "startup-lag" at the beginning of the program. Lets say you have several kb of objects with static storage duration: it will take quite some time before they are set, which might be bad for program performance. But worse: during this time, hardware registers will have out-of-reset values, including the COP register. This might in worst case cause unwanted behavior of the MCU.

One such example is all port I/O pins that are not connected to external resistors. I/O pins are always set as inputs out of reset on Freescale micros. If such pins are exposed to ESD during the startup time the MCU might be damaged, as your code has yet to either set them to outputs or to activate internal pull resistors.

The next problem is electronical: you can never rely on RAM cells during long periods of time. The program might in some cases run for years before a certain variable is used. Therefore, you cannot assume that those variables initialized by the copy-down code still have the correct values when using them.


I would recommend getting rid of the "ANSI C startup" for the above reasons.

The solution is to never rely on static initialization, but to instead set the variables in runtime, just before they are used for the first time. This makes the need for static initialization obsolete. Just be careful if you do this, as you won't be able to initialze variables with static storage duration after doing this.

static int x = 5; /* static initilization, unsafe */

static int x;
x = 5; /* runtime value assignment, safe */


In safety-critical systems, static initialization is never used, for the above mentioned reasons. An example of such systems are automotive ones, which plenty of the HC(S)08 and HCS12 micros were designed for.
0 Kudos

1,338 Views
JimDon
Senior Contributor III
"First of all, C was designed for RAM-based Unix systems in office environments."

Try core based systems, for real time telephone switching systems.
RAM was a laboratory idea at the time, and unless you meant central offices, business offices didn't have computers, at least not ones the employees used (other than programmers).
0 Kudos

1,338 Views
allawtterb
Contributor IV
In my version of CodeWarrior the start up code that would initialize this data is in Start08.c.  Have you checked this file?   
0 Kudos