[Icc-avr] Are 'local' vars in main automatuc or in bss?

Jaspers, Ton t.jaspers at cpseurope.com
Fri Oct 26 08:08:16 PDT 2007


> -----Original Message-----
> From: David Brown
> 
> Jaspers, Ton wrote:
> >  
> > 
> >> -----Original Message-----
> >> From: David Brown
> >>
> >> Hi Ton,
> >>
> >> Although it's not actually necessary, I always use "extern" 
> >> for function declarations in headers, for consistency with 
> >> declarations for variables
> >> - I don't know if there is any difference between the two.
> > 
> > Since 'extern' is a C-language keyword it is unknown what 
> may happen. 
> > Some compilers may just ignore it while others may complain 
> about it. 
> > For portability I would be very carefull with external on a 
> function 
> > prototype.
> > 
> 
> The brief checks I've now made suggest that there is no 
> difference - a 
> function declaration without a body (and no "static") is a 
> declaration 
> with external linkage, just as if it had "extern" explicitly.  It is 
> certainly the case that using "extern" with function declarations is 
> always legal in all C compilers - there is no portability question to 
> consider.  Thus I (and others on webpages thrown up by a 
> quick google) 
> recommend always using "extern" with functions declarations in header 
> files for consistency.

They are not declarations, they are function prototypes. 


> 
> > Any prototype in the header is by defenition public IMHO. Most 
> > compilers will issue a warning if the function is declared static. 
> > 
> 
> Any prototype declaration in a header *should* be a public one, 

Never declare a function in a header!


> otherwise it does not belong in the header.  But that's a programmer 
> convention - the compiler cannot enforce it in any way.
> 
> If you have a declaration of a function prototype (with or without 
> "extern", but with no "static") in a header, and later have 
> the function 
> defined as "static", then you will get an error or a warning about 
> inconsistent linkage.

That is what I said.

 
> 
> > I do very much agree with your remarks about "global". That is why 
> > tend to talk about the "scope" of a variable rather then use words 
> > as local and global. It is my experience thet those words are very 
> > confusing. The C++ naming convention is better "public" and 
> "private". 
> > But even in the C++ realm there is a constant discussion about the 
> > scope of a public or a private variable. At least it gives 
> some more 
> > options to qualify a variable together with the static keyword 
> > already known from C.
> > 
> 
> "Public" and "private" in C++ have nothing to do with 
> linkage, and are 
> only indirectly related to scope.  

 That is what I said.

> Private and public members 
> of a class 
> have the same linkage and scope - it's just that the private 
> members are 
> hidden by the compiler from direct access for functions other than 
> methods of the same class (or its friends).

In other words, they have a different scope..... 

 
> > BTW You wrote:
> > 
> > #define true  1
> > #define false 0
> > 
> > There have been countless debates about this and much bandwidth has 
> > been lost on boolean discussions. I tend to avoid booleans 
> all together 
> > in examples. In my code I usually stick to the original K&R 
> definition 
> > of zero and non-zero and avoid the whole boolean issue (who 
> cares?). 
> > 
> 
> You are correct that there have been countless debates on 
> booleans in C, 
> but there are very good reasons for using boolean types - you are 
> explicitly stating that you only expect a true or false value.  And 
> there are very good reasons for fixing them as 1 and 0.  Defining 
> "false" to be 0 is obvious, since that's standard C.  
> Defining "true" as 
> 1 is almost as obvious - it's the result of !0 and gives a consistent 
> single value for "true".

No it is not. 
Most compulers make a -1 (all ones). Check it by printing out "!FALSE".


> 
> In C99, the <stdbool.h> header explicitly defines "false" as 0 and 
> "true" as 1.

Stdbool.h  is  exactly the file that is subject of all those debates. 
Many don't use it, and for good reasons. As there are equally good 
reasons to use it as well. 

 
> > - First of all it is impossble to define a true boolean 
> variable in C. 
> > 
> 
> No - but it is impossible to get a C compiler to type-check a boolean 
> type (it will always be treated as a number - thus "bool b = 2;" is 
> legal C).  In C++, where bool is a built-in type, you can get better 
> checking.

Exactly!


> You can also use:
> 
> 	typedef enum { false, true } bool;

Yuck!
But I know there are those that use it as a substitute for a boolean.
But don't fool yourself in to believing this IS a boolean. 

The nature of the beast is exactly the same as an error number 
enummeration. The fact that it has only two members does not make it 
a boolean. It is an enumaration and only that. 

> which may give your compiler (though not iccavr, AFAIK) a 
> better chance 
> at warning about errors.  But the disadvantage of this on the AVR is 
> that a "bool" is then 2 bytes long.

Agree, and there are numerous good reasons to use an enumeration and it 
allows good error checking and there are a tousand other reasons why
this 
is good practice but it is not a true boolean. 


> > - C defines everyting not zero to be true. So this would go 
> horribly 
> >   wrong:
> > 
> > 	USHORT var = 10
> > 	if ( var == true )....  Alt:  if (!var == false )
> > AAAAAHHHRRRGGG....
> >  
> 
> It does not make logical sense to compare a numeric variable with a 
> boolean constant - your code is therefore incorrect (even though the 
> compiler accepts it).
> 
> One of the main points of using an explicit boolean type is that it 
> makes logical sense to write:
> 	bool b = true;
> 	if (b) {...}
> 
> Writing "if (b == true)" is not only risky (if you are not sure that 
> you've set b correctly), but it is logically redundant, and generates 
> less efficient code.

If it were a boolean this should not be a problem, but it is no boolean.
People that use it often falsly believe it to be a boolean but it is
just 
an enumeration. There fore it would be better to use something like:

	typedef enum { OK, ERROR } return_t ; 

Just to avoid false believes that it is a boolean.   


> Since there is no type safety on booleans, it is important to be sure 
> that you use them correctly - you can convert any C value to 
> a boolean 
> by using !!.
> 
> > - MISRA (and K&R back in the 70's) advise us to use uppercase for 
> >   constants. Thus true and false should at least be:
> > 
> > 	#define TRUE  1
> > 	#define FALSE 0
> > 
> >   Or perhaps: 
> > 
> > 	#define FALSE 0  
> > 	#define TRUE (!FALSE) 
> > 
> 
> Some of MISRA's conventions are stuck in the 70's, before computers 
> supported small letters.  

So far MISRA is the best (only) coding standard that seems to be widely 
accepted in the industry. That in itself makes it a great standard. 

> I'm not keen on shouting unnecessarily, and 

Childish nonsense reasoning. 


> thus use small letters in macro names and constants.  I'm 
> also keen on 

I rather see that a coleagues acros the globe, from any other company 
are not confused. It may be an old convention but most of us use it with

success. Anyting that  makes the code more readable, maintainable and 
more accessible to a broad audience should be supported. 


> consistency of use - code that uses a #define'd constant or a macro 
> should not have to know whether it is using a preprocessor 
> symbol or a 
> standard function or constant (or variable) - using upper 
> case only for 
> macros is an arbitrary rule which breaks that consistency.

No it is not, one can be consistend in using uppercase for macro's:

#define maxplayer	10
int maxplayers ;  

..
 10000 lines onward:

maxplayer = 11 ;  /* AIAIAIAIAI */

Can't happen if MAXPLAYER was used instead. 

Given, the compiler issues an error in this stupid example but that 
is not always the case. Just replace it with a slightly more complex 
macro that substitutes some pointer, not intended for this purpose.   
Macro's cannot be treated like ordinary functions or variables. Knowing 
something is a macro can be very usefull.


> > Other yucky things I have seen: 
> > 
> > 	typedef enum { FALSE, TRUE } bool_t ; 
> > 	typedef struct { unsigned bool:1 } bool_t ; 
> > 
> 
> I haven't seen the struct version - it would be ugly to use, generate 
> inefficient code, and would not do what the programmer seems to think 
> (it will not make "bool_t" take just a single bit).
> 
> There is nothing wrong with the enum version, except that enums are 
> sized as ints.
> 
> > And even uglier things that I shall not repeat. 
> > (On this list it's like swearing in a church).  
> > 
> > 
> > And then:
> > 
> > You did not add a warning next to the "ticker"  variable. 
> > If any function, other then the ISR writes to it your in 
> deep trouble. 
> > In my code such critical variables are surrounded by 
> warning conmments  
> > and exclamation marks. 
> > 
> 
> Whether such comments are necessary or not depends on how 
> obvious it is 
> - the "volatile" qualifier is a warning in itself, and may be 
> sufficient 
> in short code.  It's also a good example of "static" - there 
> is no way 
> to access it from outside the module.  Incidentally, it is just as 
> important to be careful about how the "ticker" variable is read as to 
> how it is written.
> 
> As a general rule in programming, variables should only ever 
> be written 
> to from one place in code, unless you have good reason and 
> take special 
> care.
> 
> > This is actually one of my tests. If a job applicant fails to spot 
> > such a critical variable, he gest a minus point. 
> > 
> 
> If the applicant fails to associate "volatile" and 
> "critical", he should 
> definitely get some minus points.  But I'd also give minus points to 

Volatile and critical are totally different things. 

A simple memory mapped peripheral (without interrupts) is still a
volatile 
variable to the code, however it is not critical. Volatile only
instructs 
the compiler to reload the variable on every use and not use a temporary

buffer (register) that may still have a copy. A critical variable may be

changed by an interrupt service while you write it, giving unpredictable

results. A critical variable needs some sort of semaphore mechanism, 
a volatile variable does not.   

 
> anyone who added a redundant comment like "!!! Warning !!! Be careful 
> when writing to this variable !!!" to a variable declared "volatile". 

Nobody gets minus points for adding comments over here. Unless it is
utterly 
useless like:

	a = 10 ;  /* a is assigned the value of 10 */

Such comments often end up at our departments notice board (culprit
unknown ;-). 
That usually teaches them.....


> Such comments shows that the programmer does not understand 
> "volatile", 

<....>



More information about the Icc-avr mailing list