Signposts: Pointers in C and Classes in C# for Inform 7 Programmers

Introduction

A while back, I wrote a post about the experience of learning something hard and new. I used two specific examples that were difficult for me: learning pointers in C last year, and learning classes in C# this year.

Now that I understand pointers and classes, I can see analogies from Inform 7 that would have helped me learn. I don’t know how many other people will come through here the same way I did – I feel like most people start with lower-level languages first – but on the other hand, I can’t be the only interactive fiction writer who wanted to get her hands goopy with underlying code.

So I’m writing this blog entry as a signpost for whoever comes after me. I hope my experience will be useful to you.

Disclaimer #1: All syntax is valid for C and C#. I won’t make any promises about what this looks like in any other language.

Disclaimer #2: These are a working analogies to increase understanding, not exact ones. There are all kinds of holes you can poke in them.

Disclaimer #3: If you’re coming at this from the other direction, as a programmer interested in gripping the guts of Inform 7, I will instead recommend Ron Newcomb’s Inform 7 for Programmers, which gives a good overview of Inform 7 from a computer science perspective. You might also wish to dig into Graham Nelson’s paper “Natural Language, Semantic Analysis, and Interactive Fiction” .

Pointers

Consider the following Inform 7 code:

The apple is a thing. The orange is a thing. The banana is a thing.
The designated object is a thing that varies.

The designated object can be the apple, or the orange, or the banana. It is not itself the apple, orange, or banana – it just points to one of those objects.

In Inform 7, I can say “the weight of the apple” and “the weight of the designated object” interchangeably, as long as the designated object is pointing at the apple. Effectively, Inform 7 dereferences the designated object on its own.

This is not the same as in C.

In C, a pointer is a reference that points to an address in the computer’s memory.

If meridian is an integer, then &meridian points to the place in memory where that integer is stored. &meridian is not itself meridian – it just points to the place where meridian can be found.

In C, I always need to state whether I want an address in memory, or whether I want to follow through and see the value found at that address.

Consider the following C code:

int meridian;
int *longitude;
meridian = 0;

longitude = &meridian;

The number 0 is stored at an address in computer memory, which is designated by meridian. If I do something with meridian, it will look at the contents of that address in computer memory. But if I do something with the pointer variable longitude, I am looking at the address itself, rather than what that address contains. If I want to see the actual contents at that address, then I need to dereference it by adding a * on the front.

In the example above, longitude will return a computer address, but *longitude (dereferencing that address) will return 0.

In the Inform code, it is possible for the designated object to be nothing. Nothing is the catch-all thing that any “thing that varies” can point at. It is not possible for the apple to be nothing, however, because the apple is itself a thing. The apple does not vary.

Similarly, in the C code, it is possible for longitude to be null. If longitude is null, then longitude is pointing at the address /0, which means it is pointing nowhere. But it is not possible for meridian to be null, because meridian is an integer, and null is not an integer.

Monodevelop ponyStructs

I’m getting to classes, but I’m going to go there by way of structs. And ponies.

I love structs. They instantly made sense to me.

Struct stands for structure, and what it actually means is a record that stores more than one value. Instead of storing a lot of values separately

char *pony1_name;
int pony1_age;
int pony1_weight;

char *pony2_name…

…you can store them all together.

typedef struct {
    char *name,
    int age,
    int weight
} pony;

Since all the records are bound together in a struct (here, the pony struct), you can access the various records in an organized fashion.

pony princessPony;

princessPony.name = “Celestia”;
princessPony.age = 500;
princessPony.weight = 800;

pony crabbyPony…

Does this look familiar? It should! Here’s the Inform equivalent:

A pony is a kind of animal. A pony has some text called the name. A pony has a number called the age. A pony has a number called the weight.

The princess pony is a pony. The name of the princess pony is “Celestia”. The age of the princess pony is 500. The weight of the princess pony is 800.

Of course, being a kind of animal inherits all the properties of things and people and animals in Inform implementation, while the princessPony in C has no existence apart from those three fields.

Classes

C# is an object-oriented language. A C# object is a data structure containing both data fields and methods.

The data fields part is simple – it’s like one of the structs we were looking at earlier. You can take every variable you need for an object, and put them all together as part of the class.

The methods are a little harder to understand. All the functions that apply to ponies, are actually part of the pony (as long as it’s a well-designed pony.)

public class Pony {
    string name;
    int age;
    int weight;

    public void feedPony (int hayTotal) {
        //code goes here
    }

    public void groomPony () {
        //code goes here
    };

    public void ridePony (int miles) {
        //code goes here
    }
}

The code above isn’t a pony – it’s a template for the existence of ponies. It’s the equivalent of the Inform code

A pony is a kind of animal. A pony has some text called the name. A pony has a number called the age. A pony has a number called the weight.

To feed (thisPony – a pony) about (hay-total – a number) pounds of hay:
   [code goes here]

To groom (thisPony – a pony):
   [code goes here]

To ride (thisPony – a pony) for (miles – a number):
   [code goes here]

In Inform, it’s not possible to trigger “groom a pony” when “pony” is a kind and there aren’t any ponies in the game. There has to be a pony for the grooming to apply to, and you have to specify which pony you want.

In C#, the same holds true. Effectively, every class in C# is the equivalent of a kind in Inform 7. Once you have princessPony, you can groom princessPony with the C# syntax

princessPony.groomPony();

just like you could groom the princess pony with the Inform 7 syntax

groom princess pony;

When calling a method on a C class, you need always to make sure that an instance of the class exists, just like making sure that an instance of a kind in Inform 7 exists. It isn’t meaningful to try this in C:

Pony.name = “TwilightSparkle”;
Pony.groomPony();

any more than it would be meaningful to try this in Inform 7:

now the name of a pony is TwilightSparkle;
groom a pony.

The exception is when you mark a class, method, or data field with the static keyword.

public class Pony {
    static int numHooves;
    string name;
    int age;
    int weight;
}

In this case, all ponies everywhere would share the same value for numHooves, and changing the numHooves on one pony would change the numHooves on all ponies. (Evil spell, perhaps?) There isn’t really an equivalent of static in Inform 7.

Conclusion

These Inform-to-C/C# comparisons should be considered analogies for greater understanding, rather than a true representation. But in both cases, they’re comparisons that helped me, so I hope they help you.

Resources that have particularly helped me:

The C Reference Guide
The C# Reference
Stack Overflow
Head-First C (Amazon)
Code Complete 2 (Amazon)

Happy coding!

Bookmark the permalink.

2 Comments

  1. Thanks for this post, it reminded me to buy a copy of the IF Theory Reader (in which Graham’s essay appears).

    Also, does this blog have a comments feed? Couldn’t find a link, but maybe because I’m on a mobile browser at the moment…

Leave a Reply

Your email address will not be published. Required fields are marked *