writes:
> I am reading "A Book on C" forth edition.
>
> In chapter 6, the author discusses "The Use of typedef". The following
> is the examples given in the book:
>
> #define N 3
>
> typedef double scalar;
> typedef scalar vector[N];
> typedef scalar matrix[N][N];
>
> The author explains that typedef is a mechanism to create new types.
That can be considered confusing. typedef only gives a name to the type
-- in effect it's the name that's new, not the type. Some other
languages, which have a similar mechanism, have chosen to make the type
itself "new". The effect being that 'double' and 'scalar' would be
considered different. That's not what C does. 'scalar' is now just
another name for 'double'.
> typedef, according to the author, increases the
> self-documenting ability of the program and using typedef is helpful
> when conceptually appropriate.
>
> The author gives the following example of what could have been written
> instead of the other.
>
> typedef vector matrix[N]; /* instead of the one below */
>
> typedef scalar matrix[N][N];
>
> My question:
>
> In the statement: typedef vector matrix[N]; being that vector is
> typedef as a scalar array, this statement says the matrix[N] is an
> array of the array vector?
Yes, though you need to be careful about using a subscript. It says
that the type matrix (no subscript) is an array of N vector.
> design question:
> An example function is given which adds vectors, three actually in the
> book,
>
> void add ( vector x, vector y, vector )
(z missing)
> {
> int i;
>
> for ( i = 0; i < N; i++ )
> x[i] = y[i] + z[i];
> }
>
> When a variable is declared to be of type vector, as in vector x, x is
> an array holding scalar values?
Not when it's a parameter! These two do different things:
vector v; // v is an array of N scalar, i.e. double
void function(vector v) // v is a pointer to scalar
In C, you can't pass arrays to functions. Writing what looks like an
array type in function header declares that parameter to be a pointer to
the array's element type. In your example, x, y and z are all pointers.
This is one of the big problems with typedefs. You need to know how the
name is defined to really know what's going on. Had vector been defined
like this:
typedef struct { scalar x, y, z; };
then you'd have been correct. A vector argument really would be passed
as a vector.
> The idea to define or think in terms of vector(s) is because of the
> problem domain?
Yes, but C is not particularly good at that, especially where arrays are
concerned. It would be nice to be able to ignore how it's actually
defined, but you can't always do that. You need a little voice in your
head telling you, every now and then, that vector is really an array.
> So, if one were writing a chess game, one could say something like:
>
> int N 8;
missing = (unless this code is from the 1970s!)
> typedef int position;
> typedef postion boardLocation[N]N];
missing [
You've used, possibly unwittingly something called a "variably modified
array" (and in a way that won't work, as it happens). For the moment,
stick with arrays where the size is defined by a macro that expands to
a simple literal.
> I'm not chess player so forgive for not being more creative with the
> names of the variable, I think of a chess board containing squares
> which have a position and will hold a piece, like a king, queen,
> knight, etc. I have not gotten to enumerations in the book yet, so,
> I'll say that those pieces will have a number associated with its
> kind.
>
> First am I abstracting that correctly? I'm I think about it
> correctly, it doesn't seem so. So, maybe all I have written is
> doesn't fit the problem correctly.
Abstraction is not all-or-nothing and it's not possible to say is some
typedef is correct or not. It all depends on how it will be used. If
you are writing a program that can solve all kind of chess-like
problems, this may be way too simple (in a more abstract notion of a
board, it need not be square, for example) but if you are going to try
to write some hyper-efficient chess puzzle solving program, your example
may be too general already.
> perhaps its enough to say:
>
> typedef int position[N][N];
>
> because that's what I think of when looking at a chess board. I mean
> that is what happens in the early code, but that code doesn't seem to
> fit the problem domain. position typed as an int? No, right. Because
> when you think of the position on a chess board its like and (row,
> column) thought, right?
There are some problems here. 'position' is not typed as an int -- it's
an array of arrays of ints. Also the word "position" means two things
in chess (a) the overall position of the game (and your typedef is fine
for that) and (b) the position of a piece. That is indeed a row and
column and you'd need something else if you wanted to represent such
things directly in your program.
> I'm trying to follow the idea that one should leave the detail off
> until later in a program. (so to speak, write)
That's a noble aim but C will get in the way of doing that again and
again. It has lots of special cases (about arrays and functions in
particular) but it also has no direct way to represent what programmers
call abstract types. Search for C and opaque structs to find out some
more about how this is sometimes tackled in large C programs.
> If this example doesn't lend itself well to discuss abstraction,
> please give another. I'll try to follow the example that you give.
Abstraction is about ignoring details, but it takes knowledge of the
purpose to know what details should be "abstracted out". Also, the
language determines how you end up thinking about abstraction, and C is
not strong in that respect. For example, almost every C programs is
lettered with loops because you can't abstract out the idea of running
through an array. This is good (for C) because it allows C compiler to
generate very efficient code, but it's not particularly good if you want
to learn about the role of abstraction in programming.
--
Ben.