why does symbol & in #define QO_PTR(q_node, q_type, q_ptr) needed?

O

ooze

typedef unsigned long PARAM;

typedef PARAM SAP;

typedef struct qnode
{
struct qnode *next;
struct qnode *prev;
}
QNODE;

typedef struct qhead
{
struct qnode *head;
struct qnode *tail;
}
QHEAD;

typedef struct
{
QHEAD qhead;
int (*srv_req) (SAP sys_sap);
SAP sys_sap;
}
SSRV_S;



typedef struct sig_s
{
struct sig_s *next;
struct sig_s *prev;
int waiting;
SAP ssrv_sap;
SIG_FUNC func;
SAP user_sap;
PARAM ident;
}
SIG_S;
/************************************************************************
* slib_init
*************************************************************************
*
*/
PUBLIC int slib_init
(
int (*func) (SAP SysSap),
SAP sys_sap,
SAP *ssrv_sap
)
{
SSRV_S *ssrv;

/* Self initialize, if needed.
*/
if (! s_initialized)
s_init ();

/* Try to allocate a sap
*/
#if MAX_SIG_SRV
for (ssrv = ssrv_pool; ssrv < ssrv_pool + MAX_SIG_SRV; ++ssrv)
if (ssrv->srv_req == NULL)
break;
if (ssrv >= ssrv_pool + MAX_SIG_SRV)
return -1;
#else
ssrv = (SSRV_S *) MEM_ALLOC (sizeof (SSRV_S));
if (ssrv == NULL)
return -1;
#endif

/* Initialize it.
*/
Q_INIT (&ssrv->qhead);
ssrv->srv_req = func;
ssrv->sys_sap = sys_sap;

/* Tell the caller the address of the SSRV_S and return success.
*/
*ssrv_sap = (SAP) ssrv;
return 0;
}


/************************************************************************
* slib_serv
*************************************************************************
*
*/
PUBLIC void slib_serv
(
SAP ssrv_sap
)
{
SSRV_S *ssrv = (SSRV_S *) ssrv_sap;
SIG_S *sig;
IPL_VALUE level;
int limit = SIG_SERV_LIMIT;

/* Call the functions for each signaled event.
*/
while (((sig = (SIG_S *) ssrv->qhead.head) != NULL) && (limit-- > 0))
{
level = IPL_SET_NORMAL ();
QO_REMOVE (sig, &ssrv->qhead, SIG_S, next);
sig->waiting = 0;
IPL_RESTORE (level);
(*sig->func) (sig->user_sap, sig->ident);
}
}




#define QO_REMOVE(q_node, q_head, q_type, q_ptr) { \
register QNODE * node = (QNODE *) (void *) q_node; \
register QHEAD * head = (QHEAD *) (void *) q_head; \
if (QO_PTR(node, q_type, q_ptr)->prev == NULL) \
head->head = QO_PTR(node, q_type, q_ptr)->next; \
else \
QO_PTR(QO_PTR(node, q_type, q_ptr)->prev, q_type, q_ptr)->next = \
QO_PTR(node, q_type, q_ptr)->next; \
if (QO_PTR(node, q_type, q_ptr)->next == NULL) \
head->tail = QO_PTR(node, q_type, q_ptr)->prev; \
else \
QO_PTR(QO_PTR(node, q_type, q_ptr)->next, q_type, q_ptr)->prev = \
QO_PTR(node, q_type, q_ptr)->prev; \
QO_PTR(node, q_type, q_ptr)->next = NULL; \
QO_PTR(node, q_type, q_ptr)->prev = NULL; \
}



#define QO_PTR(q_node, q_type, q_ptr) \
((QNODE *) (void *) (&((q_type *) (void *) q_node)->q_ptr))
 
A

Arthur J. O'Dwyer

typedef unsigned long PARAM;
[followed by a whole bunch of rather dense code and ending with]
#define QO_PTR(q_node, q_type, q_ptr) \
((QNODE *) (void *) (&((q_type *) (void *) q_node)->q_ptr))

So, after all that, you didn't write down whatever question you
may have had? That's not very bright. Whenever you have a question
that you want to ask on Usenet, it is a good idea to include the
relevant code snippets --- but don't forget to include the *question*
too!

Oh, wait, I see something up in the headers... Aha. You want to
know something about the '&' operator in C. Okay, then. You still
should have asked the question in the body of the message where we
could read it without header-diving. Let's try to answer it anyway.
Dissecting the QO_PTR macro:
#define QO_PTR(q_node, q_type, q_ptr) \
((QNODE *) (void *) (&((q_type *) (void *) q_node)->q_ptr))

((q_type *) (void *) q_node)

This expression casts 'q_node' to the 'q_type *' type. The cast
to (void *) is unnecessary; it might have been added to placate
some silly compiler's extra warnings.

(& ->q_ptr)

This computes the address of q_node->q_ptr (treating q_node as
a q_type pointer, as above). The '&' operator in C means
"address-of," and it yields a pointer to the specified object
(in this case, a pointer to 'q_node->q_ptr').

((QNODE *) (void *) )

This converts the resulting pointer into a pointer to 'QNODE',
which is probably a no-op. Certainly the cast to (void *) is
again redundant.

So, to make a long macro short, the above is precisely equivalent
to

#define QO_PTR(q_node, q_type, q_ptr) \
((QNODE *) (&((q_type *) q_node)->q_ptr))

and although I'm not going to dissect any more of that mess of
code than I already have, I think it may have been intended to be

#define QO_PTR(p, t, f) ((t*)p)->f)

[Note the intentional lack of '&' --- here I'm going by the snipped
original code, which was trying to use 'QO_PTR(...)' as an lvalue.]

-Arthur
 
A

Arthur J. O'Dwyer

#define QO_PTR(p, t, f) ((t*)p)->f)

[Note the intentional lack of '&' --- here I'm going by the snipped
original code, which was trying to use 'QO_PTR(...)' as an lvalue.]

Oops. It was using 'QO_PTR(...)->next' as an lvalue. So now I'm
not sure which one is right. :(
It's early...

-Arthur
 

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

No members online now.

Forum statistics

Threads
473,744
Messages
2,569,484
Members
44,903
Latest member
orderPeak8CBDGummies

Latest Threads

Top