Chapter 2
A C Refresher

Key Skills & Concepts

• Creating simple C command-line programs

• Using C comments

• Understanding headers, import, and include

• Understanding preprocessor statements

• Reviewing data types and operators

• Understanding C functions, basic C syntax, and using pointers

Like almost every modern operating system, language, and programming tool of any importance, Mac OS X and the iOS operating system were built using the C programming language. Not the Objective-C programming language and Cocoa framework, not the C++ programming language, but C. Objective-C is an object-oriented language built using C. Cocoa is a framework that hides difficult C programming tasks with easy-to-use objects programmed in Objective-C. But behind every Cocoa object you construct, you find C code defining the construct.

NOTE
The computer scientists Dennis Ritchie and Brian Kernighan developed C at Bell Laboratories in 1978.

You must know at least some C if you want to program using Objective-C. In this chapter, we will review basic C. This chapter assumes some programming experience—for instance, we assume you know what a method, an integer, a function, and other basic programming constructs are. Ideally, you have had at least one university course using Java or a year’s experience using Java. Experience using C# also suffices, as the language is remarkably similar to Java. As most universities teach Java these days, and Java seems to be the most prevalent language for systems developers, in this book we assume some very basic Java programming experience.

TIP
If you have never programmed before, a good reference is the Absolute Beginner’s Guide to C, Second Edition, by Greg Perry (Sams, 1994). It teaches programming and C at about the right level needed for this book. Objective-C for iPhone Developers: A Beginner’s Guide by James Brannan (McGraw Hill, 2010) also covers C and basic C constructs such as loops more thoroughly than this book. A good free reference on C is the online tutorial “How C Programming Works” on the howstuffworks web site (http://computer.howstuffworks.com/c.htm).

C Command-Line Programs

Like Java programs, C programs start with a main function. The C main function takes an integer and a pointer to a character array as inputs and returns an integer.

int main (int argc, const char * argv[])

The returned integer typically indicates the program’s success or failure. Zero usually indicates success, while a number indicates failure. Often programmers return different values as error codes. Program users can then determine what went wrong by looking up the error code in the application’s documentation.

The main function can only be implemented once in your program. When your program runs, OS X finds the main function and uses it as your program’s starting point.

Try This: Creating a Simple C Program Using Xcode

1. Open Xcode, Apple’s integrated development environment (IDE). You’ll be using Xcode for all of your iOS programming, and by the end of this book, you’ll be very familiar with its features. We’ll introduce Xcode functionality as it’s needed, but it can be worthwhile to take a little time to create a dummy project and play around with all of the buttons, navigation, and views that can be hidden or shown in Xcode’s single window interface.

2. Create a new project in Xcode by selecting File | New | New Project from the main menu. Highlight Application under Mac OS X and then select Command Line Tool, select C from the Type drop-down, and click Next. Name the project C Main Project (Figure 2-1).

3. Open main.c and note the function created by Xcode. It even created the “Hello World” message for you (Listing 2-1). Run your new application by selecting Product | Run “C Main Project” from the main menu, or by simply clicking the Run button (circular button with a black triangle) in the upper-left corner of the window. Select View | Show Debugger Area in the main menu to display the Debugger. The console output is in the lower-left pane; you’ll see “Hello World!” printed there.

Listing 2-1 The main function in a C program

#include <stdio.h> int main
(int argc, const char * argv[]) {
   // insert code here...
  printf ("Hello, World!
");
  return 0;
}

Image

Figure 2-1 Xcode New Project dialog

C Comments

C’s comment syntax is the same as Java’s. A double forward slash indicates everything following on the same line is a comment. A slash followed by an asterisk indicates everything following until the next asterisk and slash is a comment. For instance, the following are both comments. The first is a single-line comment, while the second is a multiline comment.

// This is a comment in C code.
/* This is a multiline comment in C Code.
This comment can be multiple lines. */

Comments are, of course, ignored by the compiler and are ways for you to provide code explanation for future programmers who might debug or modify your code.

Understanding Headers, Import, and Include

A header file ends with an .h file extension and contains function prototypes and preprocessing statements. A prototype is a function’s signature. A signature is a function name, a return type, and parameters, with no body. Compilers use prototypes so that functions in other files can “see” the function.

You can also say a header file declares functions. Declaring a function means you are telling the compiler you intend to define a function with the same signature as the declaration.

Code including or importing a header file declares to a compiler it might use that header file’s functions. Through the compiler’s magic, the compiler combines all files and resolves references to functions in different files, provided they all play fair and include or import the needed header files.

TIP
In standard C programs, you usually see headers included in other files. You use the #include directive when including a file in another file. In Objective-C, you typically see headers imported in other files. You use the #import directive when importing a file in another file. When importing a header file, the compiler ensures the header is only included once in your application. When including a file, no such protection is provided. Don’t worry if you don’t really understand the difference—understanding the difference is not important. Just know that when programming for iOS, use #import.

Try This: Creating a Header File

1. Create an iPhone application using the View-based Application template. Be certain you select iPhone in the Product drop-down. Name the application CreateHeaderFile.

2. In the navigation pane on the left, CTRL-click the project name and select New Group to create a new group (folder) named C Files. Add a C file to the group using the New File dialog (Figure 2-2). Name the file cwork.c, and add it to the project.

NOTE
You can use a view-based iOS application to illustrate using C in an iOS application because you can freely mix Objective-C and C in iOS programs, as Objective-C is a superset of C.

3. Type the code in Listing 2-2 into the cwork.c file. Be certain you add the function’s signature to cwork.h (Listing 2-3).

Image

Figure 2-2 Adding a C file to the project using the New File dialog

Listing 2-2 The sayHello function defined in cwork.c

#include "cwork.h"
void sayHello() {
printf("hello programmer....
");
}

Listing 2-3 The sayHello function declared in cwork.h

#include <stdio.h>
void sayHello();

The sayHello function is declared in cwork.h and defined in the cwork.c file. The sayHello function returns no value, and so its return type is void. The printf statement is declared in the standard input and output header, and so you include the stdio.h header file. Note the angle brackets; you include system libraries using angle brackets. You include headers exclusive to your project using double quotes.

4. Open main.m, import cwork.h, and add the sayHello function to the file (Listing 2-4).

Listing 2-4 The sayHello function added to main.m in the sample project

#import <UIKit/UIKit.h>
#import "cwork.h"
int main(int argc, char *argv[]) {
 NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init];
 sayHello();
 int retVal = UIApplicationMain(argc, argv, nil, nil);
 [pool release];
 return retVal;
}

5. If you have more than one project in Xcode, make sure “C Main” is the selected project in the pull-down menu and then click the Run button next to the pull-down (round button with a black triangle). The message “hello programmer....” will output to the console. You’ll probably have to select View | Navigators | Log and then pick the “Debug C Main Project” log from the list to see the output.

6. Click the button with a black square to stop the program from running.

Preprocessor Statements

The #include and #import statements are preprocessor statements. When compiling a program, the compiler processes all statements with a # sign before compiling the program; hence, the term preprocessor statement. The compiler replaces the preprocessor statements with their actual values.

Try This: Using Preprocessor Statements

1. Open the cwork.h header file from the preceding section’s project, CreateHeaderFile.

2. Type #define MYNUMBER 20 in cwork.h and save the file.

3. Modify the sayHello function to the code as in Listing 2-5. Notice that you change the sayHello function to return an integer. You must also change the cwork.h file (Listing 2-6).

Listing 2-5 The sayHello function modified to include a preprocessor statement

int sayHello() {
  printf("hello programmer....%d
", MYNUMBER);
  return 0;
}

Listing 2-6 The cwork.h file

#include <stdio.h>
#define MYNUMBER 20
int sayHello();

4. Make sure your new project is selected in the pull-down and then click the Run button to run the application. The console should now echo the message with the number defined in cwork.h.

NOTE
You define constants in header files using the #define preprocessor directive. You don’t include a constant’s type when defining a constant.

You defined a constant in cwork.h; then when you compiled, the compiler first resolved any defined constants, replacing the constant with the literal value.

Data Types and Operators

C’s basic data types are the same as Java’s and should appear familiar (Table 2-1).

Image

Table 2-1 C’s Basic Data Types

Image

Table 2-2 C’s Basic Operators

C’s common operators should also appear familiar (Table 2-2). Note the table excludes the less commonly used bitwise and shift operators.

Control, Functions, and Conditional Statements

Control statements, functions, and conditional statements all have the same syntax as their Java counterparts. Conditional if statements are the same as used in Java (Listing 2-7).

Listing 2-7 Using if statements in C

if(myInt < 2) {
  printf("the value is not equal");
  myOtherInt = 3;
} else if (myInt == 5) {
  myOtherInt = 7;
} else {
  myOtherInt = 3;
}

Switch statements are also equivalent to a Java switch statement (Listing 2-8).

Listing 2-8 C’s switch statement

switch (myInt) {
  case 1:
    myOtherInt = 3;
    printf("case one");
    break;
    case 2:
    myOtherInt = 5;
    break;
  default:
    myOtherInt = 4;
}

Loops should prove familiar if you know Java, as should the do-while loop and the for loop (Listing 2-9).

Listing 2-9 The while, do-while, and for loops using C

int i = 0;
while(i < 20) {
  printf("loop%d", i);
  i++;
}
do {
  printf("loop%d", i);
  i--;
} while(i > 0);
for(int i = 0; i < 20; i++) {
  printf("loop%d", i);
}

Arrays and Structures

C arrays are similar to Java arrays. You declare arrays the same way, but C has no new keyword; you simply start using the array (Listing 2-10).

Listing 2-10 Using a C array

int myArray[100];
myArray[0] = 1;
myArray[1] = 2;

C has structs; Java doesn’t have a struct data type. In C, a struct is similar to a class, but has no functions or inheritance (Listing 2-11).

Listing 2-11 A C struct

struct myBox {
   int length;
   int width;
}

Arrays can hold structures; for instance, you might declare an array to hold 100 myBox instances (Listing 2-12).

Listing 2-12 Using a C struct in an array

struct myBox myBoxes[100];
myBoxes[0].length = 10;
myBoxes[0].width = 2;

Functions

You declare functions the same way using C as you do using Java, only C does not restrict a function’s visibility. C has no public or private functions. As in Java, you declare a C function with a return type, a name, and argument list. You write function declarations in header files. You write function definitions in C source files. Functions that don’t return anything use void as their return type. If a function takes no arguments, you can optionally list the arguments as void.

void sayHello(void);

Although you can’t declare a function private, you can declare a function static. But a static function in C is very different from a static function in Java. In C, declaring a function static is similar to declaring a function private in Java. In C, only functions declared in the same file can use a function declared static. Static functions are useful for utility functions that won’t be used elsewhere in a program.

static void sayHello(void){ printf("hello
");}

Note that you don’t declare the static function’s prototype in a header file. You simply write the function in the source file using the function.

The printf Statement

C uses the printf statement for outputting to the standard output stream. Its declaration is as follows:

int printf( const char *format, arg1, arg2, ..., argn);

The statement takes a pointer to the characters you wish to send to the standard output stream and zero or more items for formatting. For instance, consider the following printf statement:

printf("Hello world...%d times", 22);

This statement results in the following output:

Hello world...22 times

Another common argument is %s for character strings. For instance, the following code defines a character array and then prints it.

char * hello = "hello turkey";
printf("%s
", hello);

Pointers

Java does away with pointers; however, Objective-C relies extensively upon pointers. A pointer is a reference to another variable, or more technically, a pointer is a variable that references another variable’s memory space. Think of your computer’s memory as one large cubbyhole block. A variable occupies a cubbyhole. A pointer points to the particular cubbyhole, but the pointer’s value is not the value in the cubbyhole; the pointer’s value is the cubbyhole’s address.

In Figure 2-3, the cubbyhole n is located in row 2, column 5, and its value is 12. Cubbyhole n’s value is 12, and its address is second row, fifth column. Pointer p points to n’s location, which is second row, fifth column. Pointer p’s value is not 12, but rather, second row, fifth column. This is an important distinction.

Image

Figure 2-3 Pointers as cubbyholes

You indicate pointers using the asterisk (*). Pointers point to a location in memory of another variable. The ampersand (&) indicates a variable’s address in memory.

Try This: Using Pointers

1. Create a new C command-line application, and name the application Using Pointers.

2. Modify main.c file so that it appears like Listing 2-13.

3. Select the project in the pull-down and click the Run button.

Listing 2-13 C program illustrating pointers

#include <stdio.h>
int main (int argc, const char * argv[]) {
    int anIntVal = 10;
    int *pavalue = & anIntVal;
    printf("address:%p value:%d
", pavalue, *pavalue);
    return 0;
}

In this listing, anIntVal’s value is 10, pavalue points to anIntVal’s memory address, and the printf statement prints anIntVal’s address followed by anIntVal’s value; pavalue points to anIntVal’s address while *pavalue is anIntVal’s value.

NOTE
If you are following along in Xcode, realize your address values will be different from those listed in this chapter’s example code results.

address:0xbffff628 value:10

4. Modify main so that the first two lines appear as follows:

//int avalue = 10;
int avalue;

5. Add the following line to just before the function’s return statement:

printf("value's actual value:%d
", avalue);

6. Compile and run. Listing 2-14 contains the incorrect output.

Listing 2-14 Output from C command-line program

address: 0xbffff764 value : 0
value's actual value : 0
Program exited with status value : 0.

Initializing a variable only reserves memory space; it does not assign the variable a value. When you refer to an uninitialized variable, you could get any result. You must initialize a variable with a value before using it.

7. Change the function so that anIntVal is initialized to 10 and then click Build And Go. The debugger console echoes 10, as expected.

Dereferencing a Pointer

You can also dereference a pointer by assigning the pointer’s location a new value. You do this through what’s called dereferencing the pointer. Consider the code in Listing 2-15.

Listing 2-15 Dereferencing a pointer

int a = 10;
int *b = &a;
*b = 52;
printf("value:%d value:%d",*b,a);

The third line sets the content of the memory at the address pointed to by the pointer b to the integer value 52. The address pointed to by pointer b happens to be the variable a, so changing the content changes a’s value too, as it is the location pointed to by b. Running this code results in both values printing as 52. Note that a common error is to use an uninitialized pointer or a modified pointer to accidentally corrupt memory in an unintended location in your program (for instance, accidentally using b = 52 rather than *b = 52 would change the pointer and lead to corruption if the pointer were used again later).

Pointers and Arrays

One place where pointers are useful in C programming is arrays. A common technique is to iterate through an array using a pointer as an iterator to the array’s elements. The following project illustrates this technique.

Try This: Using an Array with Pointers

1. Create a new command-line application called C Pointer Array.

2. Modify main in main.m to appear like Listing 2-16.

Listing 2-16 A C program iterating through a pointer array

#include <stdio.h>
int main (int argc, const char * argv[]) {
    int values[10];
    int *iterator;
    for(int i = 0; i < 10; i++) {
        values[i] = i * 2;
        printf("value: %d ", values[i]);
    }
    iterator = values;
    for(int i = 0; i < 10; i++) {
        printf("value(%d):%d ", i, *(iterator+i));
    }
    *(iterator+4) = 999;
    printf("
value of element at 4: %d", values[4]);
    return 0;
}

3. Select the project in the pull-down and click the Run button. Listing 2-17 is the debugger’s output.

Listing 2-17 Debugger Console output

[Session started at 2008-09-05 21:57:35 -0400.]
value: 0 value: 2 value: 4 value: 6 value: 8 value: 10 value: 12
value:14 value: 16 value: 18 value(0):0 value(1):2 value(2):4
value(3):6
value(4):8 value(5):10 value(6):12 value(7):14 value(8):16 value(9):18
value of element at 4: 999
The Debugger has exited with status 0.

What you did in this example was use a pointer to iterate through an array. The iterator points to the array’s address. The iterator first points to the element at index zero. The iterator +1 points to the element at the first position. And iterator + n points to the element at the nth position. As you iterate through the array’s values, you can use the value at the address to which the iterator points.

Summary

This chapter did not provide enough detail for you to completely learn C. In fact, this chapter hardly scratched C’s surface. But it did provide you with enough information to understand the rest of this book. You must know basic C to understand Objective-C and iOS programming. Hopefully, this chapter refreshed your memory enough to begin the next chapter. If you are familiar with Java’s basic programming structures, C header files, and C pointers, you should have no trouble understanding the next two Objective-C chapters. If you are still uncertain, you can find many free online C tutorials using Google. But don’t worry—C is kept to a minimum in this book.

NOTE
If new to programming and C programming, you might benefit from buying the book: The C Programming Language, Second Edition, by Brian W. Kernighan and Dennis M. Ritchie (Prentice Hall, 1988).

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset