Now for the part
we've all been waiting for, the basis of doing everything in C, functions.
We've talked briefly about what functions are, how they are used, how we've
even made some function calls, etc. Now it's time to really dive in and get a
concrete understanding of functions and how to write our own. Fair warning,
some of this will be repeat, so bare with me, I want to make absolutely sure
everything gets covered.
Functions IN C Programming
What is a Function?
In simple terms, a
function is a piece of code that has other smaller bits of code clumped
together to perform a certain task or set of tasks. Once again, things like
printf, getchar, and main are functions themselves so you've seen what they can
do. Now let's talk about the purpose of functions. Imagine we had a program
that asked a question very regularly to a user and gathered input from them. It
would be very inefficient for us to re-write that code every single time we
want to prompt them, so we could instead write a function called
"PromptUser" that would allow us to simply type "PromptUser()"
instead of re-writing the output and input code every time. This makes
functions valuable in that they save a lot of time and make code re-useable.
The Anatomy of a Function
Before we dive into
writing functions, we need to understand the way that they work at a core
level. All functions follow the same layout, they have a return type, a name,
and an argument list. I want you to really pay attention because we will be
introducing several new terms in this section. Functions, along with having a
return value, name, and argument list have 2 different aspects to them if you
will. Aspect one is the function declaration, aspect two is the function
definition. This can be very confusing and will for sure be one of the things
that trip you up when you first start writing C code so pay very close
attention and re-read this part regularly until you get it. This is something
pretty unique to C/C++ (though I'm sure some other language does this), so
before I cover what each of those are, let's talk about the compiler a little bit,
that will give us the reason why there are function declarations and
definitions.
Alright, so when your program is being compiled, the compiler goes through your code and part of what it does is it validates that everything is syntactically correct, it does this by reading your code from the top to the bottom. This means if you missed a semi-colon, if you missed a closing brace on a function, etc. the compiler will let you know about it. Now, all functions must be written out showing how they work, and the compiler needs to somehow be able to find those written out versions of the function. Let's say you write a function and you make a call to it inside of the main function, if the compiler reads your program from the top to the bottom, and it gets to your function, it's going to look at your function call, say to itself "Huh, well... I never saw this functions written out version anywhere, I guess they never bothered doing it, I'll let them know". This "written out" version of your function is called the function definition. If the compiler doesn't see the function definition before it hits the function call, it will throw an error. This is where function declarations come in. Whenever you write a function declaration, you are telling the compiler "Hey, I have a function, this is it's name, return type, and the arguments it takes. I am going to be making calls to it later on in the program, but you're not going to see the definition of the function until later, so don't give me an error, go look for the function definition." This is unique to C because in other languages the compiler will figure this out for you, and in some ways that's nice and it's not like it's really any more in-efficient than not doing it, but in some ways it's a lot cleaner to have function declarations so you can organize your code better (my personal opinion). As an aside, you will often hear the term "Function Prototype", this term is interchangeable with function declaration, I honestly prefer function prototype but I'm opting to use declaration for these lessons for now. I may use either so be prepared.
So with all of that now in our heads, we can look at functions properly. So to start off, we will learn about the function declaration. When we write our a function declaration, it looks like this:
Alright, so when your program is being compiled, the compiler goes through your code and part of what it does is it validates that everything is syntactically correct, it does this by reading your code from the top to the bottom. This means if you missed a semi-colon, if you missed a closing brace on a function, etc. the compiler will let you know about it. Now, all functions must be written out showing how they work, and the compiler needs to somehow be able to find those written out versions of the function. Let's say you write a function and you make a call to it inside of the main function, if the compiler reads your program from the top to the bottom, and it gets to your function, it's going to look at your function call, say to itself "Huh, well... I never saw this functions written out version anywhere, I guess they never bothered doing it, I'll let them know". This "written out" version of your function is called the function definition. If the compiler doesn't see the function definition before it hits the function call, it will throw an error. This is where function declarations come in. Whenever you write a function declaration, you are telling the compiler "Hey, I have a function, this is it's name, return type, and the arguments it takes. I am going to be making calls to it later on in the program, but you're not going to see the definition of the function until later, so don't give me an error, go look for the function definition." This is unique to C because in other languages the compiler will figure this out for you, and in some ways that's nice and it's not like it's really any more in-efficient than not doing it, but in some ways it's a lot cleaner to have function declarations so you can organize your code better (my personal opinion). As an aside, you will often hear the term "Function Prototype", this term is interchangeable with function declaration, I honestly prefer function prototype but I'm opting to use declaration for these lessons for now. I may use either so be prepared.
So with all of that now in our heads, we can look at functions properly. So to start off, we will learn about the function declaration. When we write our a function declaration, it looks like this:
"Return
Type" "FunctionName"("Arguments");
That's it really, now onto function definitions. Function definitions are almost exactly the same except you add the code that you want the function to do. For example:
"Return
Type" "FunctionName"("Arguments")
{
"Code that the
function performs";
}
There are two things you should note. One, there are braces around your function, and two, there is no semi-colon at the end of the first line. This is one of those tricky times where you have to try to remember where semi-colons do and don't go. Anytime you have a "block", or code surrounded by curly braces, you DO NOT put a semi-colon behind the opening brace, the reason is the compiler will treat that as a statement, read it, move on, look at the opening brace, and throw an error because there was nothing before the opening brace and so it thinks you made a mistake ( because you did).
Alright, now that we have covered the basics of how a function is declared, let's talk more about the inner workings of each component of a function. As we talk about each component we will develop the declaration of our first function.
Return Type
The return type is an
extremely important aspect of a function, when I create and call a function,
sometimes I will just want that function to run, I don't care about any data
inside of the function, I just care that it runs. This is fine but sometimes
you may want to get data back from the function. Say I have a function that
adds together two numbers within the function, well I might want to have the
result of the calculation sent back to be so I can use it right? Well, how
would you ever get that data? The answer is the return value. When we specify
that we want a function to pass data back to us, we have to tell the compiler
what kind of data will be getting returned back, so in the instance of a
function that returns back a result of two numbers being added, we would want
to get back an integer value. This would look like this:
int AddTwoNumbers("arguments");
So, the return value is the part of the function that specifies what kind of data gets passed back to us. Now you may be wondering how you would declare a function that just does stuff and doesn't return data back to us, and that is a great question. In this instance, we would create what is called a "void function". A void function is a function that does not pass back any data, it merely runs and does a task and that's it. Void in programming languages essentially means nothing, and I don't mean that it has no meaning, I mean it is a word that means nothing. So to create a function that returns back no data, we write the function as follows
void DoStuff("arguments");
That's it, you can pass back pretty much any sort of data or no data at all. As you can see there's really nothing to it, just specify the data type that the function will pass back to you if you want data returned back, or void if you want no data returned back.
Function Name
There's not a whole
lot to discuss here, obviously the function name cannot be a name that is taken
by C, it also can't be a name that clashes with another function that is held
in a library, so for example, you can't write your own "printf()"
because the C compiler won't know which one to use. Other than that, make sure
that function names don't contain weird characters and they can't start with a
number, and they can't have spaces.
Arguments
This is a concept
that people make much more complicated than it should be. An argument in simple
terms is a variable that will represent the variable passed to it in the
function. This will make much more sense when we actually write out our
function definition so don't worry if that is confusing for now. All arguments
passed to the function must be declared just like a variable. Why do you need
arguments by the way? Well, just like you may want data passed back to you from
the function, you may want to give the function some data to work with, pretty
simple right? So, let's put that into practice. let's finish the declaration of
our AddTwoNumbers function:
int AddTwoNumbers(int
number1, int number2);
Notice how I gave the arguments names, these will be the names that function uses to represent the data you passed to it. I will throw this out there but don't get too hung up on it. Sometimes if you are experimenting with a function and are changing the arguments frequently, it can be really annoying having to rename the argument names in both the definition and the declaration, for this reason, in the declaration if you feel so inclined, you can simply type out the data type, but you still have to specify the name of the argument in the definition:
//Function
Declaration
int AddTwoNumbers(int,
int);
//Function Definition
int AddTwoNumbers(int
number1, int number2);
To summarize that last point, you can omit the name of the argument in the declaration of the function but not the definiton, however if you do name the arguments in the declaration, the arguments in the definition have to be named exactly the same.
Conclusion
This has possibly been a pretty intense section for
some of you, some of you have possibly already worked with functions or methods
or something of this nature so for you it was probably mostly review, but
hopefully you took something away from this. Remember that functions are the
base of how everything in C works so understanding functions is literally non-negotiable
to understanding C and most high level programming as well. Before you move on,
MAKE SURE you understand this.
Post a Comment