CCS C Software and Maintenance Offers
FAQFAQ   FAQForum Help   FAQOfficial CCS Support   SearchSearch  RegisterRegister 

ProfileProfile   Log in to check your private messagesLog in to check your private messages   Log inLog in 

CCS does not monitor this forum on a regular basis.

Please do not post bug reports on this forum. Send them to support@ccsinfo.com

Non-constant variable initialization

 
Post new topic   Reply to topic    CCS Forum Index -> General CCS C Discussion
View previous topic :: View next topic  
Author Message
stinky



Joined: 05 Mar 2012
Posts: 99
Location: Central Illinois

View user's profile Send private message

Non-constant variable initialization
PostPosted: Mon Jul 06, 2015 9:48 am     Reply with quote

V4.141
Just got bit by a mistake. Kind of wish the compiler had thrown an error on me when I did this. Am i asking too much?

The line in question:
Code:
static unsigned int8 bar = savedValue(READ);

Code:
#include "16LF1829.h"
#device adc = 10
#define OSCILLATOR 16000000
#use delay (internal = OSCILLATOR)
#fuses INTRC_IO, NOWDT, NOPUT, MCLR
#fuses NOBROWNOUT, NOLVP, NOCPD, NODEBUG,   
#fuses NOPROTECT, NOCLKOUT, NOIESO
#fuses NOFCMEN, NOWRT, STVREN
#use RS232(baud = 9600, UART1, ERRORS)
#define READ   0

unsigned int8 savedValue(unsigned int8 temp) {
   static unsigned int8 foo = 2;
   if(temp)
     foo = temp;
   return foo;
}

unsigned int8 getValue(unsigned int8 temp) {
   static unsigned int8 bar = savedValue(READ);
   if(temp)
     bar = temp;
   return bar;
}

void main(void) {
  while(TRUE) {
    delay_ms(1500);
    printf("getValue == %u\n", getValue(READ));
  }
}
Ttelmah



Joined: 11 Mar 2010
Posts: 19339

View user's profile Send private message

PostPosted: Mon Jul 06, 2015 1:39 pm     Reply with quote

What's wrong?...

In the initialisation, you call 'savedValue(0)'
foo is initialised to '2', so this returns 2 and saves this in bar.

You then call getValue(0). This returns bar, which is now 2.

It works as it is coded (this in 4.141).....
stinky



Joined: 05 Mar 2012
Posts: 99
Location: Central Illinois

View user's profile Send private message

PostPosted: Mon Jul 06, 2015 2:14 pm     Reply with quote

Well the problem is that my short test program isn't accurately recreating the real problem I'm having.

The symptom was that "getvalue(READ);" was returning unexpected results the first time it was run. When I initialize variable bar with a constant value as opposed to the return value from a function.

Grr
temtronic



Joined: 01 Jul 2010
Posts: 9163
Location: Greensville,Ontario

View user's profile Send private message

PostPosted: Mon Jul 06, 2015 3:09 pm     Reply with quote

Variables in RAM can be anything on powerup unless YOU define or declare them.

It's always a very good idea to start with KNOWN data! CCS does have #zero_ram which puts 0 (zero) into ALL RAM locations.
While it does take a wee bit of time it does allow other peripherals( like an LCD module) to get 'organized' before the PIC program accesses them.

Jay
RF_Developer



Joined: 07 Feb 2011
Posts: 839

View user's profile Send private message

Re: Non-constant variable initialization
PostPosted: Tue Jul 07, 2015 2:19 am     Reply with quote

Quote:
Am i asking too much?


In my view, yes, but I can understand where you're coming from.

There's all sorts of issues of the scope and lifetime of static variables local to routines. What will happen will depend on when and how such variables get initialised.

There's also the somewhat philosphical question of whether a routine can be called and run before the program has started, or at least before user code has started? How can you run code before the code is running? In other words is it valid to call a routine during non-user initialisation? This is what I think is the step too far. I'd expect the compiler to throw an error saying it expected an expression that evaluated to a constant in that initialisation.

As it is I'd expect the statics (which in implementation terms are global variables with local scope) to be initialised in the order they occur in the source, and after any normal (i.e. non-static) global variables. As such, I'd expect your example code to "work", but not necessarily if they had been defined the other way round, and not necessarily in the same way from cold and warm starts. The reason for this would be that foo may not have been intialised by the time getValue ran. In general, in embedded code, it can also be distinctly dodgy to run code before hardware initialisation. For example, do we even know the UART will be up and running at that time? If so, would a printf work? Due to oscillator start-up arrangements, many PICs aren't even running at the correct clock speed until well into user initialisation code. Shouldn't matter for a simple variable of course, but...

This sort of thing is one reason I'm not a great fan of statics in routines. I use them from time to time, but not very often. Its all a bit clearer and better defined in object orientated languages, such as C++, where objects can be constructed at a known time and in a programmer controlled way, such as through static member functions. This example code smells a little C++-y to me, and that's may have introduced slightly inappropriate expectations of initialisation behaviour.

Regardless of how it works, and whether it works, and whether it should work, its easy to work round the issue, and that is how I tend to code anyway. That's to say don't try to be fancy, just make the variable global and initialise it expicitly during user code start-up.
Display posts from previous:   
Post new topic   Reply to topic    CCS Forum Index -> General CCS C Discussion All times are GMT - 6 Hours
Page 1 of 1

 
Jump to:  
You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot vote in polls in this forum


Powered by phpBB © 2001, 2005 phpBB Group