Monday, October 29, 2007

Fun with source control

So we're using Rational ClearCase for version control where I work, and for the most part it's a good tool, but I would really really like it if the tool made it more obvious which files were under version control and which were not, because I wound up breaking a build over the weekend after not adding one critical file to source control.

So, new rule -- I will always have at least two views. One will be for development, the other strictly for checking the build. Because modern technology is supposed to reduce the amount of work you have to do.

In other news, Gregor bit through the mouse cord on my computer last night. Whee.

Labels: ,

Saturday, October 20, 2007

The new new kid

The menagerie expands yet again.

Meet Gregor:

gregor

Your basic yellow dog. He is named after Gregor Mendel, since his genetics are ... complicated. His mom is part Golden Retriever. After that, it's a mystery. He's a water-loving dog (at least he'll play the hell out of the water in his water dish). Several people have claimed they see Lab or Chow in there. My sister-in-law the vet simply says, "he's a very mixed breed," and that we really won't know what all he has in him until he's six months old or so.

We picked him up Friday afternoon from a person in our raw food coop. She had adopted a dog from the local animal shelter who somehow missed getting spayed. Several weeks later she found she'd gotten a 7 for 1 deal. Gregor's litter is a mixed bag, with at least two separate fathers.

His first night was fairly uneventful (two accidents, but only because the sleepy apes were slow to recognize the signs of Full Puppy Syndrome). He's still fairly timid, which suits the cats just fine. Their reactions have ranged from total indifference, to cautious surveillance, to, well, this:

Lewis and Gregor

Lewis spent the entire night staring at Gregor. Thankfully he was less interested today. Gregor's been swiped at a couple of times and shook it off fairly well.

Both my wife and I grew up with dogs, but this is our first time raising a puppy. It's...different.

Labels:

Monday, October 15, 2007

A brief discussion of C declarators

So while I'm waiting for a new virtual image to finish extracting so that I can recover from the disaster that was Friday afternoon, I thought I'd write up a brief introduction to C declarators.

Declarations in C can be confusing to someone not familiar with the language. Declarations like

int x;
float y;

are fairly straightforward (x is an integer, y is a single-precision real number), but then you come across something like this:

int *(*(*foo)[10])(int (*bar)[20]);

What does that even mean? How do you read declarations like that?

C follows the paradigm of declaration mimics use: in other words, the declaration of an object must look as much like how it will be used in the code that follows. This is probably best explained with a few examples.

Suppose we have a pointer to an integer, and we want to refer to the pointed-to integer value. To do this, we would use the dereference operator, '*':

*x = 5;
printf("%d\n", *x);


The type of the expression *x is int, so our declaration looks like this:

int *x;

The keyword int is the type specifier. It provides the basic type information for item being declared. The expression *x is called the declarator. It introduces the name of the thing being declared, as well as additional type information. In the pointer example above, x is the name of the variable, and its type is "pointer to int". However, the "pointerness" of x is given by the presence of the * operator in the declarator.

Let's look at a more complicated example. Suppose we have an array of pointers to int, and we want to refer to the integer value pointed to by element i of the array. We would write

x = *arr[i];

The declaration for the array arr would look like the following:

int *arr[N];

where N is a constant integer expression for the size of the array (I'm not familiar enough with C99's variable-sized arrays to provide a usable example). The type of arr is "N-element array of pointers to int." Again, the "int-ness" of arr is given by the type specifier int, but the "array-ness" and "pointer-ness" are given by the declarator *arr[N].

Note that the * and [] operators are bound to the identifier, not the type specifier. Whitespace makes no difference; in other words, the statements

int* x;

and

int *x;

are identical. This also means that the statement

int* x, y;

only declares x as a pointer; y is declared as a regular integer.

So what about the declaration

int *(*(*foo)[10])(int (*bar)[20]);

How do you read something like that? The trick is to find the leftmost identifier and work your way out, remembering that () and [] bind before * (IOW, *a[] is an array of pointer, (*a)[] is a pointer to an array, *f() is a function returning a pointer, and (*f)() is a pointer to a function). So in this case,

foo -- foo
*foo -- is a pointer
(*foo)[10] -- to a 10-element array
*(*foo)[10] -- of pointers
(*(*foo)[10])() -- to functions
(*(*foo)[10])(int (*bar)[20]) -- taking a pointer to a 20-element array of int
*(*(*foo)[10])(int (*bar)[20]) -- returning pointer
int *(*(*foo)[10])(int (*bar)[20]) -- to int

Labels: ,