Typedef-ing structs

A

Albert

Hi, every1 (quick question):

Is this valid C89 code?

typedef struct {
int v; /* neighboring vertex */
int weight; /* edge weight */
} edge;

typedef struct {
edge edges[MAXV+1][MAXDEGREE]; /* adjacency info */
int degree[MAXV+1]; /* outdegree of each vertex */
int nvertices; /* number of vertices in the graph
*/
int nedges; /* number of edges in the graph */
} graph;
 
I

Ian Collins

Albert said:
Hi, every1 (quick question):

Is this valid C89 code?

typedef struct {
int v; /* neighboring vertex */
int weight; /* edge weight */
} edge;

typedef struct {
edge edges[MAXV+1][MAXDEGREE]; /* adjacency info */
int degree[MAXV+1]; /* outdegree of each vertex */
int nvertices; /* number of vertices in the graph
*/
int nedges; /* number of edges in the graph */
} graph;

What do you think might make it invalid?
 
B

Ben Pfaff

Albert said:
Is this valid C89 code?

typedef struct {
int v; /* neighboring vertex */
int weight; /* edge weight */
} edge;

typedef struct {
edge edges[MAXV+1][MAXDEGREE]; /* adjacency info */
int degree[MAXV+1]; /* outdegree of each vertex */
int nvertices; /* number of vertices in the graph
*/
int nedges; /* number of edges in the graph */
} graph;

MAXV and MAXDEGREE aren't defined. If you define them, to
reasonable values, then this is valid code.
 
N

Nelu

Hi, every1 (quick question):

Is this valid C89 code?

typedef struct {
int v; /* neighboring vertex */
int weight; /* edge weight */
} edge;

typedef struct {
edge edges[MAXV+1][MAXDEGREE]; /* adjacency info */ int
degree[MAXV+1]; /* outdegree of each vertex */ int
nvertices; /* number of vertices in the graph
*/
int nedges; /* number of edges in the graph */
} graph;

Yes, as long as MAXV and MAXDEGREE are defined.
 
N

Nate Eldredge

Albert said:
Hi, every1 (quick question):

Is this valid C89 code?

typedef struct {
int v; /* neighboring vertex */
int weight; /* edge weight */
} edge;

typedef struct {
edge edges[MAXV+1][MAXDEGREE]; /* adjacency info */
int degree[MAXV+1]; /* outdegree of each vertex */
int nvertices; /* number of vertices in the graph
*/
int nedges; /* number of edges in the graph */
} graph;

Assuming MAXV and MAXDEGREE are macros expanding to integer constants, I
don't see anything wrong with it, and "gcc -ansi -pedantic -Wall -W"
accepts it without complaint.

I'm a little confused how you intend to use it, though, since in
ordinary graph-theoretic usage an edge connects *two* vertices, and
yours only appears to reference one.
 
M

Mark Wooding

Nate Eldredge said:
Albert said:
typedef struct {
int v; /* neighboring vertex */
int weight; /* edge weight */
} edge;

typedef struct {
edge edges[MAXV+1][MAXDEGREE]; /* adjacency info */
int degree[MAXV+1]; /* outdegree of each vertex */
int nvertices; /* number of vertices in the graph
*/
int nedges; /* number of edges in the graph */
} graph;

I'm a little confused how you intend to use it, though, since in
ordinary graph-theoretic usage an edge connects *two* vertices, and
yours only appears to reference one.

I think that g.edges[n].v is the destination vertex of the nth
outgoing edge of node i. I don't understand why the edges and degree
arrays need MAXV + 1 items, but I'm sure it makes sense to Albert.

-- [mdw]
 
K

Kaz Kylheku

Albert said:
Hi, every1 (quick question):

Is this valid C89 code?

typedef struct {
int v; /* neighboring vertex */
int weight; /* edge weight */
} edge;

typedef struct {
edge edges[MAXV+1][MAXDEGREE]; /* adjacency info */
int degree[MAXV+1]; /* outdegree of each vertex */
int nvertices; /* number of vertices in the graph
*/
int nedges; /* number of edges in the graph */
} graph;

Assuming MAXV and MAXDEGREE are macros expanding to integer constants, I
don't see anything wrong with it, and "gcc -ansi -pedantic -Wall -W"
accepts it without complaint.

I'm a little confused how you intend to use it, though, since in
ordinary graph-theoretic usage an edge connects *two* vertices, and
yours only appears to reference one.

There is something called a ``directed graph'' in graph theory. The edges have
a direction, and can be thought of as navigable in one direction only.

Note that, in the above structure, the array:

edge edges[MAXV+1][MAXDEGREE]; /* adjacency info */

can in fact represent the one-way-navigable edge of a directed graph.

Given a vertex number u, and an edge index e, the expression:

edge[e].v;

retrieves the vertex adjacent to vertex u, via edge e. So there are
in fact two vertices involved.
 
A

Albert

What do you think might make it invalid?

Not sure, it just seems weird in C.
Is it correct to say that every time the compiler sees 'edge' it
replaces those four letters with 'struct { int v; int weight; }'
?

The constants in upper-case are defined but I haven't put them in this
post. Mark Wooding and Kaz Kylheku's interpretations of the data
structure are correct (if I understand them correctly).
 
N

Nelu

Not sure, it just seems weird in C.
Is it correct to say that every time the compiler sees 'edge' it
replaces those four letters with 'struct { int v; int weight; }' ?

No. A macro is replaced before compilation. Typedef creates a synonym
that is a proper type.
For example:

#define mpchar char *
typedef char * tpchar;

mpchar p1, p2;
tpchar p3, p4;

Which of p1, p2, p3 and p4 are pointers?
 
K

Kaz Kylheku

Not sure, it just seems weird in C.
Is it correct to say that every time the compiler sees 'edge' it
replaces those four letters with 'struct { int v; int weight; }'
?

A typedef name does not behave like a naive preprocessor macro. It does behave
like a name which represents a type, when it it is mentioned in the right
context, in a scope where it is active. The preprocessing stages are blind to
such context.

But could typedefs be processed within the compiler by a (Lisp or Scheme-like)
macro-expansion process over an abstract syntax tree?

Note that in the following example, x and x have different types:

struct { int foo; } x;
struct { int foo; } y;

The structs are anonymous (do not have a tag), so each one is
a unique type. But in the following example, x and y have the same type:

typedef struct { int foo; } foo_t;

foo_t x;
foo_t y;

If occurences of the foo_t type are replaced by the struct in a naive way,
or in the wrong processing stage in the compiler, this will break; x and y
will have different types.

In order for x and y to have the same type above, foo_t must be bound to the
unique type that comes from reducing the tree node "struct {int foo;}" to that
unique type. Objects declared using foo_t are then declared using that unique
type, and not the original syntax from which it came.

This is why I'd hesitate to call it macro-expansion; the substitution has to be
done after some semantic translation has already happened, rather than upfront.

Macro expansion generally means that we manipulate the syntax of a language
before doing anything semantically deep with it; (at least in a logical sense,
macro expansion could be interleaved with semantic actions, just not for the
same items).

Since typedef names give us type equivalence which the corresponding syntax
replacement does not, we have to conclude that the binding of typedef names is
to a representation of type that is somewhat deeper than surface syntax; hence
typedef names are more like variables, than macros.
 
K

Keith Thompson

Albert said:

No, only p1, p3, and p4. Because mpchar is a macro, it's replaced by
the token sequence char * before any semantic analysis is done. So
the above, after preprocessing, becomes:

/* #define mpchar char * */
typedef char * tpchar;

char * p1, p2;
tpchar p3, p4;

The next-to-last line declares p1 as a char*, and p2 as a char. (If
you don't believe me, try copying Nelu's code into a small program
that tries to treat p2 as a pointer.)
 
A

Albert

The next-to-last line declares p1 as a char*, and p2 as a char.  (If
you don't believe me, try copying Nelu's code into a small program
that tries to treat p2 as a pointer.)


Touche (with e acute accent). Failed to read the problem carefully.
 
C

CBFalconer

Albert said:
Not sure, it just seems weird in C. Is it correct to say that
every time the compiler sees 'edge' it replaces those four
letters with 'struct { int v; int weight; }' ?

The constants in upper-case are defined but I haven't put them
in this post. Mark Wooding and Kaz Kylheku's interpretations of
the data structure are correct (if I understand them correctly).

If you have put a line reading:

"#define edge struct (int v; int weight;)"

somewhere earlier in your source file, yes, provided the edge word
is properly delimited.
 
C

CBFalconer

<< letters with 'struct { int v; int weight; }' ?
No. A macro is replaced before compilation. Typedef creates a
synonym that is a proper type.

Where does he have, or mention, either a typedef or a macro?
 
I

Ian Collins

CBFalconer said:
<< letters with 'struct { int v; int weight; }' ?

Where does he have, or mention, either a typedef or a macro?
Late to the party an inattentive again?

typedef struct {
int v; /* neighboring vertex */
int weight; /* edge weight */
} edge;
 
K

Kaz Kylheku

<< letters with 'struct { int v; int weight; }' ?

Where does he have, or mention, either a typedef or a macro?

That's generally what it means to take ``edge'' and replace them with ``struct
....''. Recognizing one piece of text and replacing with another is macro
expansion. Albert referred to ``four letters'', which clearly means that it's
something treated as raw program text.
 
N

Nelu

<< letters with 'struct { int v; int weight; }' ?

Where does he have, or mention, either a typedef or a macro?

First post:

<OP>
typedef struct {
int v; /* neighboring vertex */
int weight; /* edge weight */
} edge;
</OP>

and, then, before my post, as a reply to Ian Collins' follow-up:

<OP>
Is it correct to say that every time the compiler sees 'edge' it
replaces those four letters with 'struct { int v; int weight; }'
?
</OP>
 
A

Albert

Hi, every1 (quick question):

Is this valid C89 code?

I was doing a problem from a previous programming competition and I
ridded the program of every error except for one which I believe is
associated with the following:

typedef struct something {
int variable;
} lots[100];

Why isn't this allowed? I should probably create a tiny program
containing this code and compile it b4 I ask though.
 
I

Ian Collins

Albert said:
I was doing a problem from a previous programming competition and I
ridded the program of every error except for one which I believe is
associated with the following:

typedef struct something {
int variable;
} lots[100];

Why isn't this allowed?

Define not allowed. There's nothing wrong with the construct, but it
probably doesn't do what you expected.

What did you expect?
I should probably create a tiny program
containing this code and compile it b4 I ask though.

b4? English, please.

Why didn't you compile it?
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,755
Messages
2,569,535
Members
45,007
Latest member
obedient dusk

Latest Threads

Top