Structure pointer question

T. William Wells bill at proxftl.UUCP
Tue Jul 5 16:25:39 AEST 1988


In article <391 at teletron.UUCP>, andrew at teletron.UUCP (Andrew Scott) writes:
> Now that my original question has been answered, I have another:
>
> Suppose that I've constrcuted a library of functions that operate on a
> "generic" data structure called 'struct message'.  This structure is an
> incomplete type; the library functions merely deal with pointers to this
> structure but not with the fields within.
>
> It is now permissible to use this library with different declarations of
> 'struct message' *in the same program*?  I'm not planning on converting
> between multiple kinds of "messages", I just want to have multiple modules
> in the program able to use the previously constructed library with data
> structures applicable to (and used in) only one module.
>
> My initial guess is that it would work, given that C requires all structure
> pointers to have the same format and provided that I compile the different
> modules of the program seperately (so that the compiler doesn't see the
> multiple declarations).

Strictly speaking, such a program does not have to work,
however...

I pointed out that, unless some code generation is done at link
time, a compiler can't really make assumptions about incomplete
structure types and thus can't use different representations for
structure pointers; however, another message points out that
there is one relatively common environment where this is not
true: interpreters. I'd say that, if you are using a system with
separately compiled modules that what you are doing is likely to
work, but if you did it in a interpreter system, that it may not.

Also, I know of one compiler system that could defer part of the
code generation to link time. The Amsterdam Compiler Kit's
program building goes compile, link, and assemble; the linker can
fix up structure pointer references if necessary.  The compiler
used for MINIX is based on this compiler system.

The correct solution is to have your library deal with void *.
If a raw void * bothers you, use typedef void *MESSAGE; and then
type everything as MESSAGE. You will also probably want to have
macros that do the references to library functions if these
pointers are to be passed as arguments or returned as values by
functions in the library.

I'll guess that you are building some kind of message passing
system and that your library has something to do with queueing
and dequeing. On that presumption, here is how I might write an
enqueue function.

These are in the public include file:

	#define msg_queue(x) (lib_msg_queue((void *)(x)))
	extern int      lib_msg_queue();
	extern void     *msg_dequeue();

These are in the library itself:

	typedef struct Q_ELT {
		struct Q_ELT *q_next;
		void    *q_message;
	} Q_ELT;

	int
	lib_msg_queue(msg)
	void    *msg;
	{
		Q_ELT   *qptr;

		if (!(qptr = (Q_ELT *)malloc(sizeof(Q_ELT)))) {
			return (-1);
		}
		qptr->q_message = msg;
		...enqueue the message
		return (0);
	}

	void *
	msg_dequeue()
	{
		Q_ELT   *qptr;
		void    *msg;

		qptr = ... dequeue the message;
		if (!qptr) {
			return (0);
		}
		msg = qptr->q_message;
		free(qptr);
		return (msg);
	}

If you have a compiler with prototypes, your job is even easier.
Change the name of lib_msg_queue to msg_queue and place this in
the public include file:

	extern int      msg_queue(void *msg);
	extern void     *msg_dequeue(void);

Does that help?



More information about the Comp.lang.c mailing list