View previous topic :: View next topic |
Author |
Message |
jonnewbill
Joined: 29 Jul 2015 Posts: 10
|
ANSI C Compliance Bug in Static&Global Var Initializatio |
Posted: Mon Sep 07, 2015 3:43 pm |
|
|
I have encountered a bug in ANSI C compliance with the CCS C Compiler
Code: | int16 a;
int16 b = 0;
main()
{
printf("a = %ld b = %ld\n\r", a, b);
} |
The output from the above program is
Even though in ANSI C the declarations for "a" and "b" are equivalent. The ANSI C standard is that all static and global variables without explicit initialization are to be initialized to zero. Generally all these uninitialized "zero-vars" are collected into a single data block and initialized in the C startup routine. This is not happening in CCS C Compiler.
The workaround is to always explicitly initialize every static and global variable to zero. This however means potential errors and added work when porting C code from other compilers.
Jon Newbill
Bitworks Systems Inc. _________________ I remember the days before OPS (Other Peoples Software) when all the bytes in my computer were written by me. |
|
|
PCM programmer
Joined: 06 Sep 2003 Posts: 21708
|
|
Posted: Mon Sep 07, 2015 5:46 pm |
|
|
Quote: | The workaround is to always explicitly initialize every static and global
variable to zero. |
A better work-around would be to add #zero_ram:
Code: |
#zero_ram // Add this line
int16 a;
int16 b = 0;
main()
{
printf("a = %ld b = %ld\n\r", a, b);
}
|
|
|
|
temtronic
Joined: 01 Jul 2010 Posts: 9221 Location: Greensville,Ontario
|
|
Posted: Mon Sep 07, 2015 5:58 pm |
|
|
I've done PCM P's way since V2.456 or there abouts.
I do NOT trust so called 'standards', 'wizards' or any other 'helpful' things that others feel 'should' be the default in MY programs.
Jay |
|
|
FvM
Joined: 27 Aug 2008 Posts: 2337 Location: Germany
|
|
Posted: Sun Oct 04, 2015 3:24 am |
|
|
Quote: | I do NOT trust so called 'standards' |
If you can't rely on a C compiler's basic compliance with the C standard, you are lost. CCS C does generally comply with the ANSI C standard, but there are a few exceptions.
One exception is that you need to specify #zero_ram to get all uninitialized global variables zeroed at program start. There are other differences regarding the default size and signedness of data types with the 8-Bit compilers. |
|
|
temtronic
Joined: 01 Jul 2010 Posts: 9221 Location: Greensville,Ontario
|
|
Posted: Sun Oct 04, 2015 5:22 am |
|
|
The problem I've seen with 'standards' is that they change over the years. The best hardware example is the com port of a PC. It WAS the 'standard' that pin 2 of the I/O connector WAS transmit (from PC), then it magically became receive(to PC) when they went to a 9 pin connector. Of course, now there is NO RS232 comport on the PC....sigh.
Even Microchip has strayed from well known standard 'defaults'. Case in point, whether the ADC section is defaulted to I/O pins or not. Most do but newer ones don't....sigh..
You just case rely upon 'standards' better to add code to be sure it might work the way you want it to !
Jay |
|
|
Ttelmah
Joined: 11 Mar 2010 Posts: 19498
|
|
Posted: Sun Oct 04, 2015 10:56 am |
|
|
There is also another thing here, the idea of talking about 'ANSI C', as if this is a standard.
It isn't. You have to add the year involved. CCS attempts to be compliant with ANSI C99.
ANSI C99, specifically says 'All global variables must be initialised before the program starts, or are undefined'..... |
|
|
RLScott
Joined: 10 Jul 2007 Posts: 465
|
|
Posted: Sun Oct 04, 2015 3:25 pm |
|
|
temtronic wrote: | The problem I've seen with 'standards' is that they change over the years. The best hardware example is the com port of a PC. It WAS the 'standard' that pin 2 of the I/O connector WAS transmit (from PC), then it magically became receive(to PC) when they went to a 9 pin connector. Of course, now there is NO RS232 comport on the PC....sigh.
Even Microchip has strayed from well known standard 'defaults'. Case in point, whether the ADC section is defaulted to I/O pins or not. Most do but newer ones don't....sigh..
You just case rely upon 'standards' better to add code to be sure it might work the way you want it to !
Jay |
As for RS-232, there is no reason to expect pin 2 of a DB-25 to mean the same thing as pin 2 of a DB-9, so your example is not an illustration of a standard changing.
As for the practice of initializing variables to zero, I am glad that CCS does not do this by default. I can imagine a program with many static variables that is also bumping up against its limit in program space. In such a program it is better to let the programmer decide which variables really need to be initialized at program start. And often a program has need of re-initializing some variables at various points. In that case programmer could save some code by using his own init routine at times when he needs it, rather than having the compiler do it once and only once at program start. _________________ Robert Scott
Real-Time Specialties
Embedded Systems Consulting |
|
|
Ttelmah
Joined: 11 Mar 2010 Posts: 19498
|
|
Posted: Mon Oct 05, 2015 12:30 am |
|
|
There is another very good reason not to initialise things, which is to do with the actual environment.
We are dealing with embedded processors. As such the possibility of waking using the watchdog appears. For this it is critical to be able to declare global variables that are _not_ changed on boot. Sequence then becomes to test the restart_cause, and if this is a normal power up, only then initialise the variables. If the cause is a wake up from watchdog, it becomes vital to be able to restart retaining the old values. A difference that only applies to code on chips like this. Some compilers add the keyword 'persistent' to make variables be uninitialised. However this is just as much 'not part of the standard' as any other way of doing it.... |
|
|
|