MacDevCenter    
 Published on MacDevCenter (http://www.macdevcenter.com/)
 See this if you're having trouble printing code examples


What's Your Function?

by Seth Roby
08/01/2003

The biggest journey begins with a single step, and the largest program starts with a line of code. Now that we've begun, we have to put one foot in front of the other and make progress toward our goal of understanding enough C to learn Objective-C. With each line of code that we lay down and learn from, we get a little bit further toward that goal.

But one of the biggest things we need to learn is not something we can see in any one line of code, but an idea that our code needs to follow, a basic structure that will form all of the code we write. In fact, one could say that in C, this is not a structure, but the structure.

C is what is called an imperative language, which means that the basic way that all things are done is by telling the computer imperative statements, one after the other. You group these statements together with functions. You make functions to start, stop, and run your application. You make functions to check things, set things, read things, and write things. You make functions to do every bit of bit flipping, every line of line drawing. C lives and breathes functions.

The main Function

The first function we will write, appropriately, is the main function. This function is the first one that any C, C++, or Objective-C program calls, and it starts the ball rolling in each of these languages.

Our main function will use the code from our last lesson, but first, we need a place to put it. So before we learn any code, we have to pause for a small aside on how to use Apple's Developer Tools.

If you're using Mac OS X versions 10.0 to 10.2 (Jaguar), the tool you will be using is Project Builder. This is an optional install on most systems, so you will have to find the Developer Tools CD that came with your Mac or your System Software and install it, or download it from Apple here.

If you are using Mac OS X 10.3 (Panther), you'll be using Xcode, which at the time of this writing is still prerelease software. I will attempt to give directions for both systems, but be warned that the details for Xcode may change after this article. Xcode is also optional software, so again, you will need to find the Developer Tools CD that came with your computer or system software and install it, or download it from Apple here.

The first thing you do once you have installed either application is launch it. You can find the tool you're using in /Developer/Applications. You might want to put it in your dock if you plan on using it often, or if you just want to get to it easily for the remainder of the series.

Related Reading

Cocoa in a Nutshell
A Desktop Quick Reference
By Michael Beam, James Duncan Davidson

If this is the first time you are opening the Apple Developer Tools, a window might open asking you a few questions. Just hit Next until the window closes, as the defaults are perfectly fine, and can be changed in the Preferences later. After that window closes, another window might open telling you everything that's new about this version. Read this if you want, and then close it to continue with the lesson.

Setting Up a Project

The first thing we need to do is make a Project, which is Apple Developer Tools speak for "group of files that are used to make a program." The Developer Tools help you keep track of these files and build the program. Under the File menu, choose New Project.... This will open a dialog asking what type of Project you want to create. Apple's Developer Tools support a wide array of different coding projects, which is where the names for both versions come from: they are all complex Projects centered around Code.

Later on, you will want to develop code using the various "Cocoa" Projects, toward the top of the list. But for now, we are going to develop what Apple calls a "Tool," specifically a "Standard Tool." This is the simplest Project, as it includes only one file and the supporting system around it. Once you select "Standard Tool," click the Next button at the bottom of the window. The window will now ask you where you want to keep the Project, and what you want to name it. I keep all of my projects in a Developer folder in my home folder. This has the added benefit that some extras that augment Apple's Developer Tools use this directory to keep things in.

So hit the Choose button, and make a folder named Developer in your home folder. Choose to put the project in there, and choose a name for your project. For now, we'll use "C is For Cocoa." Click Finish, and your first project window will open.

Notice a few things before we start. The window is named after your Project. On the top is a toolbar full of actions we are going to be using often. If you are using Xcode, click on the Editor button to open a pane on the window where you can preview the code. We'll get to the rest later. On the left is a list of the things you will be working with during your development. On the right is a preview of the thing that you are currently focused on, and currently editing. This design might remind you of iTunes, where you choose a playlist on the left, and the playlist's contents appear on the right.

First let's look on the left. Click on the disclosure triangle next to the Source folder (in Xcode, you first need to open the folder named after your project). This will show a file that's called main.c. Click on it, and the file's contents will show up on the right. Right now, it's a very basic skeleton of a file, but even so, it can show us a few things.

The first thing you should notice is how the file is split up into two sections because of the extra line of whitespace. The first section is only one line (the one that says #include <stdio.h>), and is a bit of magic that we'll get to in a later lesson. For now, just ignore it and know that it lets us do what we need to do.

The next block is a function. Yes, it's been a little bit of a digression, but we found one. This is a function definition. As this is our first real live function, let's study it a little. Here's what my version of the Developer Tools gave me:

int main (int argc, const char * argv[]) {
    // insert code here...
    printf("Hello, World!\n");
    return 0;
}

You'll notice the familiar beginning: int. Then the next token is main, which is the name of the function. After that come a lot of things between some parentheses. This, if you recall how we called a function, will remind you of the list of arguments, and that's exactly what it is. Each argument is defined in turn, and is given a type, a name, and any other distinctions we wish to add to it. The first argument of main is of type int, and is named argc, for argument count. The next argument is named argv, for argument values or argument vector, depending on who you ask. Either way, its type is const char * and it's got some funny square brackets at the end. Both of these things are important, but they're not important now, so we'll leave them to a later lesson.

Next is something else new. The { opens a block of code, which ends a few more lines down (line 7 in the example above), with the }. Anything within these curly-brackets is "within the block." Blocks will help us to understand what a function is and why you want to use them.

Basically, a function is a bit of code that you want to use over and over again. It does a little bit of work that you can change slightly by passing it different arguments. The code it runs is what is within its block, which is often called the function body.

Here, the main function has three lines of code. The first is a comment, so we know that the computer ignores it. The second is a call to another function, and it's a function we've seen before: printf. This call to printf tells the computer to print "Hello, World!", followed by a return (that's what that crazy \n is: the escape sequence for a newline). If you've ever done any programming before, you know that "Hello, World!" programs are the first thing you ever do. Here's a C example for you, and you don't have to write any of it.

The last line of code in the block is new to us. To figure that line out, we look back to the beginning. We noticed the int at the start of the function, but we didn't say what it was for. The answer to that question and the meaning of the last line in the block are intertwined.

Functions in C do some work that you want them to do as defined by the code in the function body, and then they can give you back a result. So you can make a function that finds out what time it is (and indeed there is such a function), but that function needs some way to tell whatever bit of code that called it what time it actually is. To do this, the function returns a value. That value, like all the data C knows about, is stored in a variable, and that variable, like all variables, must have a type. The main function returns a value of type int, which is our familiar integer. In fact, main is defined by the C language to return an integer, but the functions that you write can return any type you want.

So knowing that main returns an integer, this last line of code in the block tells the computer to return zero, which is an int. By convention, returning zero from main means that the program completed correctly. Any other return value is assumed to be an error.

Build and Run

So before we play around with this code that we just read through, let's give it a whirl.

Up at the top of the window, in the toolbar, there is an icon that looks like this if you're running Project Builder:

PB's Build and Run Button.

And like this if you're running Xcode:

Xcode's Build and Run Button

This is the "Build and Run" button, which will compile the project that you're working on (make the code into language the computer can execute), and then run the program you made. If you click this now, you will build and run the code contained in this project, which is just the main function we've examined. Do this now, and watch the computer execute the code, printing the message into the window (in Xcode, you have to go to the Debug menu and select Show Run Log to see the message). If you get an error, make sure that everything is copied exactly.

So that's what you can do without writing a single line of code. But we already have a few lines of code sitting around from our last lesson, so let's pull those out and give them a whirl. Delete the comment and the call to printf, and paste in our code. Now your main.c file should contain this:

#include <stdio.h>

int main (int argc, const char * argv[]) {
	//Computes our favorite number
	int favoriteNumber = (3 * 4) / 2;	//is anyone's favorite number not an int?
	favoriteNumber = favoriteNumber + 2;
	/* now let's tell the world
		what our favorite number is! */
	printf("My favorite number is %d!", favoriteNumber);
	return 0;
}

And again, click the Build and Run button (remember that if you're in Xcode, you have to select Show Run Log from the Debug menu). Now, instead of "Hello, World!", what prints is "My favorite number is 8!" And you made it print that.

But what else can you make it do? We'll explore our boundaries a little bit by defining our own function. So below the main function, put the following snippet of code:

int integerForSeedValue(int seedNumber) {
	//code goes here
}

This is another function definition, so called because it defines exactly what the function does. There are a few things to notice here, the first being that the name of the function follows the same style we use for variables: take all of the words that make up what you're describing, smash them together with each word capitalized, and make the first letter lowercase.

Notice also that our function has one argument, and that argument is described in the parentheses. Our code defines its type, which is an int, and we give it a name, seedNumber, which again follows our variable-naming scheme. Every time we want to call this function, we must pass one integer into it, or the compiler will complain and the program will crash.

Note where the curly brackets are placed. This method is the traditional C style, with the opening bracket on the same line as the function name. Objective-C uses this same style, but C++ puts the opening bracket on the next line, all alone. Since C ignores whitespace, both are perfectly legal, and since a lot of people use C++ a lot, they're more used to it down there on the next line. So don't be alarmed if you see it move around a bit.

Lastly, we're returning an integer, but we have no code that says what we're returning. This is obviously a problem, but before we fix our function up, let's hit the Build button and see what the Developer Tools think. We want to build and not run for right now, because our code is not correct, and we need to see how the Developer Tools inform us of this fact. The Build button looks like this in Project Builder:

PB's Build Button.

And like this in Xcode:

Xcode's Build Button.

When you hit the Build button, the project window moves around a bit to make it obvious it's doing something. In Project Builder, an area opens up to tell you about how the build is going. In Xcode, the Errors and Warnings item on the left will open up. In either case, you will see the message warning: control reaches end of non-void function.

What's this? It's a warning. Warnings tell you that while the compiler was trying to understand your code, something seemed a little odd, and it decided to tell you about it. This warning tells you that you have made a function whose definition claims the function returns a value (an int, in our case), but the function body doesn't ever return anything. That would be just fine in a void function (which we'll get to later), but it's a little odd here, so the compiler gives you a warning. An error is a more serious problem that means that your code cannot be compiled as written, and you need to fix the problem before you can run. Both show up in the same places, but warnings will allow you to run your program, although they often foretell errors that will crash your program at run time. Click on the text and the developer tools will helpfully take you to the offending piece of code. For now, it's obvious that our new function is the culprit, but in huge projects, this click-and-go is a lifesaver.

For now we have a simple fix to our problem. We simply add a line into our function, so it looks like this:

int integerForSeedValue(int seedNumber) {
	//code goes here
	return 0;
}

Click Build again, and you will see that the warning disappears. It is a good practice to write code that has neither warnings nor errors, and we will strive to do this as we complete more complex code.

Spice Up the Function (Just for Fun)

But for now you may wonder about our little fix. Our function ignores the input we give it, doesn't do anything useful, and always returns the same thing. What is this, a Windows error dialog?

So let's spice up our function a little. Change the function to the following:

int integerForSeedValue(int seedNumber) {
	return seedNumber - 3;
}

Now we're doing some work in our function, and we're returning something that changes, based on what we're given. We return the variable seedNumber, minus the constant 3. But you might be wondering how we can use the variable seedNumber without first issuing a variable declaration, and that is a very good question. The answer is that we did a variable definition, it's just not as visible as the others we have done. This definition is inside of the parentheses, in the argument list. There, when we note what arguments this function takes, we are also declaring these arguments to exist.

So now that we have a function, we need to call it. Up in our main function, replace the line

favoriteNumber = favoriteNumber + 2;

with the slightly altered line:

favoriteNumber = integerForSeedValue(favoriteNumber + 2);

Now we're calling our integerForSeedValue function from our main function. When the computer executes that line of code, it will look into our integerForSeedValue function and run all of the code in its code block before moving on to the next line of code in main. Note that while the computer is executing the lines in integerForSeedValue, the variable seedNumber will have the evaluated value of favoriteNumber + 2, which is 8. So integerForSeedValue will return 8-3, or 5. Let's build our program and see. Hit the Build button, to make sure we don't have any warnings or errors.

Well, what do you know? We do. The warning we got this time is warning: implicit declaration of function `integerForSeedValue'. What does that mean? Well, we know what a variable declaration is, and we know that we can't use variables until we declare them. And if we click on this warning, it takes us to where we're using our function, so it's a pretty logical step to think that functions need to be declared before use, too, and that's exactly right.

So we add in one line above main, to declare our function. Now our file looks like this:

#include <stdio.h>

int integerForSeedValue(int seedNumber);

int main (int argc, const char * argv[]) {
	//Computes our favorite number
	int favoriteNumber = (3 * 4) / 2;       //is anyone's favorite number not an int?
	favoriteNumber = integerForSeedValue(favoriteNumber+2);
	/*now let's tell the world
		what our favorite number is! */
	printf("My favorite number is %d!", favoriteNumber);
    return 0;
}

int integerForSeedValue(int seedNumber) {
	return seedNumber - 3;
}

Looks familiar, doesn't it? What we've done is take the function, knock it's block off, and present it here with a semicolon. That is enough for the compiler; this simple line is the function declaration we needed, and another Build confirms it when the compiler doesn't complain. Run the program, and you see that our favorite number is now 5, just like it should be!

Wrapping Up

Wow, we've made some progress in this lesson! We learned about the tools we'll need to use every day we're developing, we compiled and ran "Hello World!", we took a few lines of code and made it into a program, we learned how to recognize, implement, declare, and call functions, and we learned how to get information from the Developer Tools about problems with our code, and fix them before they're problems with our programs.

But we still have a long ways to go. Next time, we'll dive into flow control, which affect the way our code gets executed, so we can do more complex things than the "list of things to do" approach we have been taking. That will give us a lot of the tools we need to make more complex programs with the knowledge we've gained.

Seth Roby graduated in May of 2003 with a double major in English and Computer Science, the Macintosh part of a three-person Macintosh, Linux, and Windows graduating triumvirate.


Read more Programming With Cocoa columns.

Return to the Mac DevCenter.

Copyright © 2009 O'Reilly Media, Inc.