Functions

C is a function-based language (K&R 4.1). A function is a block of code defining what should happen; when other code calls (invokes) that function, the function’s code does happen. A function returns a value, which is substituted for the call to that function.

Here’s a definition of a function that accepts an integer and returns its square:

int square(int i) {
    return i * i;
}

Now I’ll call that function:

int i = square(3);

Because of the way square is defined, that is exactly like saying:

int i = 9;

That example is extremely simple, but it illustrates many key aspects of functions.

Let’s analyze how a function is defined:

int1 square2(3int i) {4
    return i * i;
}
1

We start with the type of value that the function returns; here, it returns an int.

2

Then we have the name of the function, which is square.

3

Then we have parentheses, and here we place the data type and name of any values that this function expects to receive. Here, square expects to receive one value, an int, which we are calling i. The name i (along with its expected data type) is a parameter; when the function is called, its value will be supplied as an argument. If a function expects to receive more than one value, multiple parameters in its definition are separated by a comma (and when the function is called, the arguments supplied are likewise separated by a comma).

4

Finally, we have curly braces containing the statements that are to be executed when the function is called.

Those curly braces constitute a scope; variables declared within them are local to the function. The names used for the parameters in the function definition are also local to the function; in other words, the i in the first line of the function definition is the same as the i in the second line of the function definition, but it has nothing to do with any i used outside the function definition (as when the result of the function call is assigned to a variable called i). The value of the i parameter in the function definition is assigned from the corresponding argument when the function is actually called; in the previous example, it is 3, which is why the function result is 9. Supplying a function call with arguments is thus a form of assignment. Suppose a function is defined like this:

int myfunction(int i, int j) { // ...

And suppose we call that function:

int result = myfunction(3, 4);

That function call effectively assigns 3 to the function’s i parameter and 4 to the function’s j parameter.

When a return statement is encountered, the value accompanying it is handed back as the result of the function call, and the function terminates. It is legal for a function to return no value; in such a case, the return statement has no accompanying value, and the definition states the type of value returned by the function as void. It is also legal to call a function and ignore its return value even if it has one. For example, we could say:

square(3);

That would be a somewhat silly thing to say, because we have gone to all the trouble of calling the function and having it generate the square of 3 — namely 9 — but we have done nothing to capture that 9. It is exactly as if we had said:

9;

You’re allowed to say that, but it doesn’t seem to serve much purpose. On the other hand, the point of a function might be not so much the value it returns as other things it does as it is executing, so then it might make perfect sense to ignore its result.

The parentheses in a function’s syntax are crucial. Parentheses are how C knows there’s a function. Parentheses after the function name in the function definition are how C knows this is a function definition, and they are needed even if this function takes no parameters. Parentheses after the function name in the function call are how C knows this is a function call, and they are needed even if this function call supplies no arguments. Using the bare name of a function is possible, because the name is the name of something, but it doesn’t call the function. (I’ll talk later about something it does do.)

Let’s return to the simple C function definition and call that I used as my example earlier. Suppose we combine that function definition and the call to that function into a single program:

int square(int i) {
    return i * i;
}
int i = square(3);

That is a legal program, but only because the definition of the square function precedes the call to that function. If we wanted to place the definition of the square function elsewhere, such as after the call to it, we would need at least to precede the call with a declaration of the square function (Example 1-3). The declaration looks just like the first line of the definition, but it is a statement, ending with a semicolon, rather than a left curly brace.

Example 1-3. Declaring, calling, and defining a function
int square(int i);
int i = square(3);
int square(int i) {
    return i * i;
}

The parameter names in the declaration do not have to match the parameter names in the definition, but all the types (and, of course, the name of the function) must match. The types constitute the signature of this function. In other words, it does not matter if the first line, the declaration, is rewritten thus:

int square(int j);

What does matter is that, both in the declaration and in the definition, square is a function taking one int parameter and returning an int. (In a modern Objective-C program, though, the function declaration usually won’t be necessary, even if the function call precedes its definition; see Modern Objective-C Function Declarations.)

In Objective-C, when you’re sending a message to an object (Chapter 2), you won’t use a function call; you’ll use a method call (Chapter 3). But you will most definitely use plenty of C function calls as well. For example, earlier we initialized a CGPoint by setting its x element and its y element and by assigning its elements values in curly braces. But what you’ll usually do to make a new CGPoint is to call CGPointMake, which is declared like this:

CGPoint CGPointMake (
   CGFloat x,
   CGFloat y
);

Despite its multiple lines and its indentations, this is indeed a C function declaration, just like the declaration for our simple square function. It says that CGPointMake is a C function that takes two CGFloat parameters and returns a CGPoint. So now you know (I hope) that it would be legal (and typical) to write this sort of thing:

CGPoint myPoint = CGPointMake(4.3, 7.1);

Get Programming iOS 6, 3rd Edition now with the O’Reilly learning platform.

O’Reilly members experience books, live events, courses curated by job role, and more from O’Reilly and nearly 200 top publishers.