Learn C for Cocoa
This tutorial explains the parts of C you need to get started with Cocoa.
We cover most concepts in a page or two instead of an entire chapter.
Don't skim. Give your complete attention to each section.
You should already know at least one scripting or programming language,
including functions, variables and loops. You'll also need to type
commands into the Mac OS X Terminal.
This
Cocoa Dev Central
tutorial is written by
Scott Stevenson
Copyright © 2004-2015 Scott Stevenson
Skills Check
Make sure you understand the code below before continuing.
function display_area_code ($code)
{
print ("$code ");
}
$area_codes[0] = 408;
$area_codes[1] = 650;
$area_codes[2] = 510;
/* this is a comment */
$count = 3;
for ($i = 0; $i < $count; $i++)
display_area_code ($area_codes[$i]);
This example has a function, a print statement, a comment, an array, variables,
and a loop. If all of this makes sense to you, you're ready to use this tutorial.
To download the examples instead of typing them, grab the following disk
image:
All examples for tutorial
You must have Xcode installed to build software on Mac OS X, though most of the
code here will probably work on any OS.
A Sample C Program
This is your first C program. Paste this example into a plain
text editor and name the file test1.c
#include <stdio.h>
main ()
{
printf ("I'm a C program\n");
}
The #include <stdio.h> statement includes the C code that deals
with input and output. We need this for the printf function.
The next line defines the main function that all C programs have.
Finally, I call the printf function with some text to display on the
command line. The \n inserts a new line after the text.
Use GCC to Compile
Open Terminal and change to the directory that contains the test.c file. Enter
the command gcc test1.c -o test1. To run the program, enter
./test1 on the command line.
If see errors, go back and make sure you pasted the sample source code correctly.
host% gcc test1.c -o test1
host% ./test1
I'm a C program
host%
The -o parameter for gcc sets the name of the program
file. If you leave this out, the program will just be called
"a.out".
About the Compiler
You need to use a compiler to convert your C source
code into a binary program before you can run it. A compiled
program often runs much faster than a script. Much of Mac OS X is written in C.
In this tutorial, we're using gcc on the command line to compile, but Xcode
provides a graphical front end to the same tools.
Portability
A C program can usually only run on the same type of computer it was compiled on.
If you compile your C source on Mac OS X, you can't run the program on
something like Linux. You have to recompile the same code on Linux.
In more complex C programs, you have to change the code for
each platform you compile for. This is called porting the code.
C Differences
It's easier to learn C if you can compare it to a language you already know. Below
is a list of concepts that are new to you if you're coming from a scripting
language like PHP or Perl:
compiler |
creates useable programs from C source |
typed variables |
kind of data that a variable contains |
typed functions |
the kind of data returned from a function |
header files (.h) |
declare functions and variables in a separate file |
structs |
groups of related values |
enums |
lists of predefined values |
pointers |
aliases to other variables |
These are all pretty simple concepts. The C language is not that complicated,
it's just that all the different pieces can be put together in a way that makes things
seem confusing.
Without pointers, C would look almost identical to PHP. Pointers are tricky
conceptually, but Cocoa abstracts you from the most of the those details for
basic programming.
You're not going to learn about pointers in this
tutorial. The focus here is getting you up and running quickly. You can go
back and revisit pointers when you want to get into more serious programming.
Typed Variables
In scripting languages, you can use variables freely. You're allowed
to change the contents of a variable from an integer number, to a
decimal number, and finally to text:
$variable = 2;
$variable = 1.618;
$variable = 'A';
In C, the rules are more strict. You have to declare the type of
data a variable will hold, and the type can't change later. Here's the C
equivalent of the snippet above:
int variable1 = 2;
float variable2 = 1.618;
char variable3 = 'A';
Notice that I had to define three separate variables in the C
version, one for each type of data. You only have to declare the variable
type once, though:
float variable2 = 1.618;
variable2 = 3.921;
variable2 = 4.212;
Available Types
For our purposes, these are the built-in C types you need to know about:
int |
integer numbers, including negatives |
0, 78, -1400 |
unsigned int |
integer numbers (no negatives) |
0, 46, 900 |
float |
floating point decimal numbers |
0.0, 1.618, -1.4 |
char |
single text character or symbol |
'a', 'D', '?' |
Although you won't see them as often, be aware of the double type,
which is a version of float that can hold larger decimal point numbers,
and long, which is a larger version of int.
C also allows you to create your own variable types.
Typed Functions
In C, you have to declare the type of data you plan to return from a
function. The return type can be any C variable type, and is placed
to the left of the function name.
int numberOfPeople ()
{
return 3;
}
float dollarsAndCents ()
{
return 10.33;
}
char firstLetter ()
{
return 'A';
}
You can also specify the return type as void. For now, you
can just think of this as saying that no value will be returned:
void printHello ()
{
printf ("Hello\n");
}
Types for Parameters
It's also necessary to define types for values passed into a function.
Unlike scripting languages, though, you can't set default values.
int difference (int value1, int value2)
{
return value1 - value2;
}
float changeDue (float amountPaid, float costOfItem)
{
return amountPaid - costOfItem;
}
Declaring Functions
In C, a function has to be declared before any other code
can call it. You can put all the functions before main(), but this
quickly becomes a lot of work.
The solution is a function prototype. It
looks like a function definition, but it doesn't
have curly braces and ends in a semicolon:
int difference ( int value1, int value2 );
float changeDue ( float amountPaid, float costOfItem );
In a function prototype, you specify the type of data to return,
the function name, and a type for each value passed into the
function.
Here's an example. Paste the contents into a file called test2.c
#include <stdio.h>
int sum ( int x, int y );
main ()
{
int theSum = sum (10, 11);
printf ( "Sum: %i\n", theSum );
}
int sum ( int x, int y )
{
return x + y;
}
I include stdio.h so I can use printf. After that,
I declare the sum function using a prototype. Inside
main, I call the sum function, and store the result
in a variable called theSum.
Because the sum function
specifies a return type of int, I need to declare theSum as
an int too. The variable type should match the function
return type.
I display the contents of
theSum using printf. At the bottom is the sum function
itself, which just adds the two number together. This is called
the function implementation.
Compile the Example
Open Terminal and change to the directory which contains test2.c.
Then, type "gcc test2.c -o test2" to compile.
Type "./test2" to run the program.
host% gcc test2.c -o test2
host% ./test2
Sum: 21
host%
Format Strings
You might be wondering what that %i in the above example means. In
some scripting languages like PHP, you can freely embed variables inside of
double quotes:
$var1 = 3;
$var2 = 8;
print ("First value: $var1 second value: $var2");
In C, you can't embed variables directly inside text. You have to use a
format string with markers for the variables:
int var1 = 3;
int var2 = 8;
printf ("First value: %i second value: %i", var1, var2);
int |
%i / %d |
unsigned int |
%u |
float |
%f |
char |
%c |
The format string is everything inside the double quotes. Put a
% marker
anywhere you want the contents of a variable to appear.
The letter you put next to the percent symbol depends on the type of value you want
to display. In this case, I use
%i because I have
int variables.
The format string is followed by a comma, and the name of one variable for each
marker you used. It's critical that the variable names come
after the closing quote and a single comma.
Cocoa programs use
NSLog instead of
printf, but the formatting rules are
almost identical.
Type Casting
Sometimes you need to convert a variable from one type to another. For
example, you might have a float that you need to use in a function
that requires an int.
Sometimes you can just use an int variable in place of a float without
any errors, but it's better to do the conversion yourself. This conversion
is called casting.
int multiply (int x, int y)
{
return x * y;
}
int trips = 6;
float distance = 4.874;
int approxDistance = (int)distance;
int total = multiply ( trips, approxDistance );
So casting is basically putting the desired type in parantheses,
just to the left of the value.
The results of casting vary on what you're converting to and from.
Converting a float to an int will simply chop off the digits after the
decimal point. Casting does not round numbers up.
Casting temporarily converts the contents only, not the
variable itself. In the above example, distance is a still a float
variable after the cast, so you have to use the cast again every time
you want it treated as an int.
More Casting Examples
Here's a way to call the function without using the approxDistance
variable. I can just do the cast inside the function call instead:
int result = multiply (trips, (int)distance);
Sometimes you need to convert the data returned from a
function into a different type. You use the same form for that:
int multiply (int x, int y)
{
return x * y;
}
float result;
result = (float) multiply (3, 6);
From the function definition, I can see that multiply returns an int.
I want to store the result in a float, so when I call the function, I use a
(float) cast before the function name. The result variable will
have a value of 18.0.
Header Files
Since you need to declare all functions in C before you can use them,
it would be helpful to group related function declarations
and manage them in a single place. This is what header files do.
Header files are vital in large projects because they give you
an overview of source code without having to look through every
line of code.
Create a Header File
Here's a sample header file. Copy
the contents into a file named math_functions.h
int sum (int x, int y);
float average (float x, float y, float z);
Here are the function implementations. Paste the contents into a file
called math_functions.c
int sum (int x, int y)
{
return (x + y);
}
float average (float x, float y, float z)
{
return (x + y + z) / 3;
}
In the average function, I separated the addition from the
division using parenthesis. If I didn't, only the last number
would be divided. It's always good practice to group all the values used
in a single math operation.
Using Header Files
Here's a program that uses the functions declared in the header file. Copy the
contents into a file called test3.c
#include <stdio.h>
#include "math_functions.h"
main ()
{
int theSum = sum (8, 12);
float theAverage = average (16.9, 7.86, 3.4);
printf ("the sum is: %i ", theSum);
printf ("and the average is: %f \n", theAverage);
printf ("average casted to an int is: %i \n", (int)theAverage);
}
After the standard stdio.h, I include math_functions.h.
This allows the program call the sum and average
functions.
Inside main, I call the sum function and store the result in an int
variable. Then I call the average function and store the result in a
float variable.
The program uses printf three times. Once using the %i symbol for
the int variable theSum, once using %f for the float
variable theAverage, and once with %i by casting
theAverage to int.
The stdio.h include is in angle brackets because it's from a C library
(more on that later). The math_functions.h file is specific to this program,
so it's in double quotes.
Compile the Example
You should now have three files, all in the same directory:
math_functions.h - math function declarations
math_functions.c - math function implementations
test3.c - the actual program
Switch back to Terminal, and change to the directory which contains the
three files. To compile the program, type "gcc test3.c math_functions.c -o test3".
Run the program by typing "./test3"
host% gcc test3.c math_functions.c -o test3
host% ./test3
the sum is: 20 and the average is: 9.386666
average casted to an int is: 9
host%
This time we gave gcc two input files: test3.c and
math_functions.c. The gcc command combine the contents the two .c files
into a single program.
I don't need to list the header file math_functions.h on the command line.
I just use the #include statement instead.
Structs
Structs are structured groups of variables. Here's an example of a
struct designed to store song information.
typedef struct {
int lengthInSeconds;
int yearRecorded;
} Song;

It looks like I'm declaring two int variables, but I'm actually
creating a new type of variable. The
typedef statement assigns
a name to the struct. In this case, the name is
Song.
Every
Song variable I declare will hold two values:
lengthInSeconds and
yearRecorded. In this case, both
fields hold int values, but a field in a struct can be any type (even another struct).
Once you define a struct, you can use it the
same way you'd use int, float or char. You can make as many
Song variables as you want, each with their own length and year.
You assign a value to field in a struct using the dot syntax:
Song song1;
song1.lengthInSeconds = 213;
song1.yearRecorded = 1994;
Song song2;
song2.lengthInSeconds = 248;
song2.yearRecorded = 1998;
I created a variable called song1 and gave it a type of Song.
I then set the length and year using the dot syntax. The variable song2 is also a Song, but it has different values for its fields.
Structs in Functions
Functions can specify structs as input or output. These function declarations
and the struct itself can be put in a header file.
Paste the following code into a file called song.h
typedef struct {
int lengthInSeconds;
int yearRecorded;
} Song;
Song make_song (int seconds, int year);
void display_song (Song theSong);
In this header file, I defined the Song struct. I also declared two
functions, make_song and display_song. Now we need to create the method
implementations.
Paste the following code into a file called song.c
#include <stdio.h>
#include "song.h"
Song make_song (int seconds, int year)
{
Song newSong;
newSong.lengthInSeconds = seconds;
newSong.yearRecorded = year;
display_song (newSong);
return newSong;
}
void display_song (Song theSong)
{
printf ("the song is %i seconds long ", theSong.lengthInSeconds);
printf ("and was made in %i\n", theSong.yearRecorded);
}
The make_song function takes two int values and returns a Song
struct. The display_song function takes any Song struct as input, and
displays its values. Note that the make_song function calls display_song when a
new Song is created.
I had to include song.h in song.c because the functions use the Song
type. You have to include the song.h header in any file which uses Song in any way.
Structs in Use
Now we need a program that uses the song.h and song.c files.
Paste the following code into a file called test4.c
#include <stdio.h>
#include "song.h"
main ()
{
Song firstSong = make_song (210, 2004);
Song secondSong = make_song (256, 1992);
Song thirdSong = { 223, 1997 };
display_song ( thirdSong );
Song fourthSong = { 199, 2003 };
}
In this program, I create two Songs using the make_song function. Rather than
using make_song for the third song, I use a special syntax that involves
putting comma-separated values between curly brackets.
Note that when I don't call make_song to create a song, the display_song
function doesn't get automatically called. So on the next line, I call it manually.
The fourth song is created in the same way, but since I never call display_song
for it, it's never displayed in Terminal.
It's better to use a function to create a new struct instance so you can
control the process more precisely. In this case, I can automatically display
information about each Song that's created.
Compile the Example
Now that you have song.h, song.c and test4.c, you can compile them and see the output.
Switch to Terminal, change to the directory that contains the three files, and enter the command
"gcc test4.c song.c -o test4".
Type "./test4" to run the program.
host% gcc test4.c song.c -o test4
host% ./test4
the song is 210 seconds long and was made in 2004
the song is 256 seconds long and was made in 1992
the song is 223 seconds long and was made in 1997
host%
Constants
The value of a variable can change as a program runs. By contrast, a constant
is assigned a value once in the declaration, and that value can't change
until the program is restarted.
const float goldenRatio = 1.618;
const int daysInWeek = 7;
You can have a constant version of any of the standard C variable types. The only
trick is that you have to supply a value when you create the variable.
Enums
We could spend a lot of time on enums, but in the spirit of focusing on the
relevance to Cocoa, we're going to make this really, really simple.
Here's an enum from Cocoa's NSString class which defines text search options:
enum {
NSCaseInsensitiveSearch = 1,
NSLiteralSearch = 2,
NSBackwardsSearch = 4,
NSAnchoredSearch = 8,
NSNumericSearch = 64
};
Apple uses enums in Cocoa to group a series of related constants.
This is often used as a way to set a "mode" for a particular function. The
values of the constants don't really matter, just the name.
Here's an example of an enum in use. Don't worry about understanding what
this code does, just focus on how the enum is being used:
[string compare:anotherString options:NSCaseInsensitiveSearch];
[string compare:anotherString options:NSLiteralSearch];
Libraries
The stdio.h file included in every example is a header file for part of the standard
C library. A library is a
collection of reusable code.
It can define things like functions, structs, constants and enums.
There are thousands of third party C libraries available. Some are free and come with
.c source files. Others require a fee and provide header files and documentation but
no source code.
To use a third party library, you have to compile and "link" to it. For example, if I
wanted to write a C program that could talk to a MySQL database, I could link to
the libmysql library and include its headers in my program.
When you use code created by others, it's important to know what the terms of
use are. Some licenses, for example, may require you that share all of the source code
for your application.
If you're feeling adventurous, take a look in
/usr/include, which is a
standard place for C header files.
Final Example
Here's a final program that uses almost all of the concepts from
this tutorial. You need to have the following files from before:
math_functions.h - math function declaration
math_functions.c - math function implementations
song.h - Song struct and related function declarations
song.c - implementation of the Song functions
Paste the contents of this example into a file called final.c
#include <stdio.h>
#include "math_functions.h"
#include "song.h"
main ()
{
const int numberOfSongs = 3;
printf ("total number of songs will be: %i\n", numberOfSongs);
int i;
for (i = 0; i < numberOfSongs; i++) {
printf ("loop trip %i ", i);
}
printf ("\n");
Song song1 = make_song (223, 1998);
Song song2 = make_song (303, 2004);
Song song3 = { 315, 1992 };
display_song (song3);
int combinedLength = sum (song1.lengthInSeconds, song2.lengthInSeconds);
printf ("combined length of song1 and song2 is %i\n", combinedLength);
float x = (float) song1.lengthInSeconds;
float y = (float) song2.lengthInSeconds;
float z = (float) song3.lengthInSeconds;
float averageLength;
averageLength = average (x, y, z);
printf ("average length is: %f as a float ", averageLength);
printf ("and %i as an int\n", (int) averageLength);
}
This example may look complex, but it's just repetition of the same concepts.
If there's anything here that doesn't make sense, go back and read the
previous sections.
Compile the Example
Make sure you have the four files previously mentioned plus final.c, all in
the same directory. Switch to Terminal and change to
the directory which contains the files. Enter the command gcc final.c song.c math_functions.c -o final.
Type ./final to run the program
host% gcc final.c song.c math_functions.c -o final
host% ./final
total number of songs will be: 3
loop trip 0 loop trip 1 loop trip 2
the song is 223 seconds long and was made in 1998
the song is 303 seconds long and was made in 2004
the song is 315 seconds long and was made in 1992
combined length of song1 and song2 is 526
average length is: 280.333344 as a float and 280 as an int
Wrap Up
We've covered a lot of ground in a relatively small amount of space. If you
understand the code in the final example, you should be ready to start learning
the basics of Objective-C and Cocoa.
As you do more programming, you'll need to look into some more advanced topics
such as pointers and memory management. Some starting points for those
are listed below.
Theocacao:
C Memory and Arrays
Theocacao:
C Pointers and Dynamic Memory
Love it? Have suggestions?
Send feedback on this tutorial.
Copyright © 2004-2015 Scott Stevenson
Made with
TextMate