Objective-C Lesson 14: Structs and Unions

Structs

Structs are a C construct that allows for grouping of items into one variable. For example, if you wanted to store a date, you could use three separate variables for the day, month, and year. This approach would work if you had to store one or two dates. But if you’re writing a calendar application, for example, having to keep track of which month belonged with which year would be a nightmare. Fortunately, C structs allow you to group these values into one type. The syntax for a date struct might look like this:

struct date {int month; int day; int year;};

You can then define a variable of this type as struct date today, yesterday;. However, we can use our friend the typedef statement to make this code a bit neater:

typedef struct {int month; int day; int year;} Date;
Date today, yesterday;

To access values within a struct, you use the dot operator. To set the month, you might write today.month = 5;. To get a value, the same procedure applies: int year = today.year;.

In action, it might look like this:

#import <Foundation/Foundation.h>

int main (int argc, char *argv[]) {
    NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
    typedef struct {int month; int day; int year;} Date;
    Date today;
    today.month = 5;
    today.day = 22;
    today.year = 2011;

    NSLog(@"Today's date is %i/%i/%i", today.month, today.day, today.year);
    [pool drain];
    return 0;
}

Initializing Structures

The fastest way to initialize a structure is to enclose the values in a pair of braces:

Date today = {5, 22, 2011}; You can list fewer values, and they will be filled in until the end of the values you list. The remaining values will be undefined.

Date today = {5}; This sets the month to 5, but leaves the remaining fields with garbage values from RAM.

You can also initialize the values out of order:

Date today = {.day = 22, .month = 5; .year = 2011};

Structs Within Structs

C allows you to put structs with structs. For example, Apple provides the CGRect data type, which defines a data type by being a struct containing a CGPoint and CGSize:

struct CGRect {
   CGPoint origin;
   CGSize size;
};
typedef struct CGRect CGRect;

You can then access the values by chaining the dot operator. To get the width, you would write float width = rect.size.width;

Unions

Unions are a data construct that allow you to store more than one type of data in the same storage area. They are typically used in more advanced constructs. If you needed a variable, x, that could hold either an int, float, or char type, you could define a union as such:

union mixed {int i; float f; char c;};

Unions are syntactically similar to structs, but inside there are not three pieces of memory, only one. You can used the mixed type to hold either an int, or float, or char, but not two at the same time. Setting a new value overrides the previous, and you must ensure that you pull out the same type as you put in; otherwise you’ll get strange results. Accessing the field is the same as with a struct:

// x is such a union type
x.c = 'E';
x.f = 39.28;
x.i = 7/2;

You can initialize the union with a single value in braces, and it will be assigned to the first field:

union mixed x = {'$'};
// You can also specify a field
union mixed x = {.f = 3.14};

Structs and unions are more advanced C data types that are nonetheless used in lower-level frameworks, such as Apple’s Quartz framework for drawing stuff to the screen. It is important to realize that they are not objects, though. They are merely data types, with no methods to access.

This post is part of the Learn Objective-C in 24 Days course.


Previous Lesson Next Lesson