dmac257:
In reading through some of the questions and answers Pixelk stated in another thread
it seems more efficient to split my main function ( MenuUpdate ) into many small functions
and since I am new to C the only understanding I have is that a function is "simular" to a subroutine but I would like to know how they differ and HOW to write your own functions. The only programming I have done prior to getting my Arduino Uno is in BASIC and I had a small collection of subroutines that I could just paste together to "get the job done"
While playing with LEDs I wrote the following code:
if (lastLED == 13)
lastLED = 10;
else lastLED = lastLED +1;
but COULD it have been something like:
void whichLED ( ) {
if (nextLED == 13) {
nextLED = 10;
}
else {
lastLED = lastLED +1;
}
And do i need all the { } brackets?
First off - yes, you could have made a function like that (though you are missing an end bracket), and yes (for certain values of "yes") you need the brackets. Now to explain (this might grow into TL;DR, so bear with me):
First off, a function is defined simply as:
{returntype} {functionname}({parameterlist}) {
// your code here
}
Where {returntype} is the type of value the function returns, {functionname} is the name of the function, and {parameterlist} is a comma-delimited list of parameters (and their type) to pass into the function.
So - in the case of your function (which I have taken the liberty to clean up so as to align the brackets - this is important for maintenance reasons, BTW):
void whichLED() {
if (nextLED == 13) {
nextLED = 10;
}
else {
lastLED = lastLED +1;
}
}
The {returntype} is "void" (meaning it doesn't return a value), the {functionname} is whichLED, and the {parameterlist} is empty (no parameters passed in). Now, one thing I notice about your function is that there are a couple of variables (nextLED, lastLED) in it that don't seem to have any definition. This brings up the concept of "variable scope"; that is, where a variable is defined, and where it can be used and modified.
In the case of your function, if these variables were defined outside of the function (as is seen in many Ardunio sketches), these variables have what is known as "global scope" - they are, in essence, "global variables", in that any function can update them, and any function can use them. Ordinarily, this is seen as a "bad thing" (tm) in software development, and can lead to all sorts of headaches; however, in a microcontroller environment like the Arduino, global-scope variables sometimes can't be avoided. You should strive, however, to limit their use where you can.
So what other kinds of variables are there besides "global"? Well, in the world of functional programming, there's a second type called "local". These variables are declared and used within a function. They can only be accessed within their originating functional block (ie, that which is enclosed by the brackets), and upon exit from the block, their value is "lost" (there are ways around this using pointers and other bits of arcane knowledge, but that would go beyond the scope of this small tutorial). So, for instance, if you had this function:
int myFunction() {
int myLocalVar = 5;
return (myLocalVar);
}
A call to myFunction() would return "5" as an integer value (notice how I defined the variable locally as an integer type, and how my function return type is integer as well), but if you attempted to use the variable "myLocalVar" outside of the function (and it wasn't defined outside of the function as a separate variable), you would either get an error, or you would get the last value of the variable. I'll attempt to show this:
void main() {
int myLocalVar = 10; // myLocalVar = 10
int x = myFunction(); // x = 5
x = myLocalVar; // x = 10
}
int myFunction() {
int myLocalVar = 5;
return (myLocalVar);
}
Even if you defined the same variable as a global, variable definitions inside a function are still local to that function, such as:
int myGlobalVar = 10; // myGlobalVar = 10
void main() {
int myLocalVar = myGlobalVar; // myLocalVar = 10
int x = myFunction(); // x = 5
x = myLocalVar; // x = 10
x = myGlobalVar; // x = 10
}
int myFunction() {
int myLocalVar = 5;
int myGlobalVar = 3; // this looks weird, you would never name a local variable with the name "global"
return (myLocalVar);
}
Now - what if you wanted to pass one or more values to the function to operate on them? Simple:
void main() {
int x = myFunction(3, 2); // x = 6
}
int myFunction(int myVar1, int myVar2) {
int myLocalVar = 5;
return (myLocalVar + myVar1 - myVar2);
}
What if you wanted to return more than one value? This is possible, but not easy, so I won't get into it deeply here - but it basically involves passing into the function the address pointer of a variable, grabbing the value at that address (the value of the variable), manipulating it, then storing it back (this in effect should give you an idea of how to access a variable local to a function outside of it, by returning from the function the address of the local variable). Please note that what I have written, while all possible, should be done very carefully, if at all. On a microcontroller (or any system, for that matter), it can lead to sleepless nights and loss of hair (and sanity).
One last thing (not really - if you really want to understand this, you need to pick up a good book on C programming): Say you want to have a local variable inside a function that retains its value between function calls? Use the "static" keyword:
void main() {
int x = 0;
for (int i=0; i < 10; i++) {
x += myFunction(3);
}
}
int myFunction(int myVar1) {
static int myLocalVar;
myLocalVar += myVar1;
return (myLocalVar);
}
Oh - I almost forgot; you were asking about whether the brackets were absolutely needed. The short answer is "sometimes". The better answer is "always". For instance this:
if (nextLED == 13) {
nextLED = 10;
}
else {
lastLED = lastLED +1;
}
...could be written as this (IIRC):
if (nextLED == 13)
nextLED = 10;
else
lastLED = lastLED + 1;
IIRC, if you only have a single statement in a code block (between the brackets), the brackets can be done away with. However, if you have multiple statements, then you need the brackets. Its best just to always use the brackets. Remember also to always line up the brackets in a form which suits you best (as well as have a consistent indentation style); this will aid in future maintenance. There are generally two main styles in use in C - the style I have used above, and the following style:
if (nextLED == 13)
{
nextLED = 10;
}
else
{
lastLED = lastLED + 1;
}
They each have their proponents and detractors; I personally prefer the style that I have used throughout this post, but you may prefer the more aligned version. One last thing (I promise!) - I have put comments in my code examples which -are not- good examples of coding style; comments in real code should serve to define what is going on with the code, and not simply state what the code is doing (which can be easily seen from reading the code). However, in these examples, I did this so-as to make it clear to someone unfamiliar with what is going on, well, what is going on. Hopefully that wasn't too confusing.
I hope this TL;DR posting helps in some manner...good luck!
