From owner-freebsd-hackers Wed Feb 21 11:24:26 2001 Delivered-To: freebsd-hackers@freebsd.org Received: from earth.backplane.com (earth-nat-cw.backplane.com [208.161.114.67]) by hub.freebsd.org (Postfix) with ESMTP id F2DB637B67D for ; Wed, 21 Feb 2001 11:23:44 -0800 (PST) (envelope-from dillon@earth.backplane.com) Received: (from dillon@localhost) by earth.backplane.com (8.11.2/8.9.3) id f1LJNWl24375; Wed, 21 Feb 2001 11:23:32 -0800 (PST) (envelope-from dillon) Date: Wed, 21 Feb 2001 11:23:32 -0800 (PST) From: Matt Dillon Message-Id: <200102211923.f1LJNWl24375@earth.backplane.com> To: "Jacques A. Vidrine" Cc: freebsd-hackers@FreeBSD.ORG Subject: Re: portability sanity check References: <20010221094228.A93221@hamlet.nectar.com> Sender: owner-freebsd-hackers@FreeBSD.ORG Precedence: bulk X-Loop: FreeBSD.ORG :Is the following portable and safe? : :Given n different structure declarations, where each structure begins :with the same member type, can any instance of any of the structures :be cast to the (pointer) type of the first member? : :e.g. : : struct foo { : const char *s; : ... : }; : : struct bar { : const char *s; : ... : }; : : int gefahr(struct foo *Foo, struct bar *Bar) { : return strcmp((const char *s)Foo, (const char *s)Bar); : } : :Likewise if the first member were a more complex data type, but :nevertheless the same between the different structures. : :It seems safe to me, but I can't explain why :-) : :Cheers, Probably safe, but not a good idea. Why not simply pass blah->s to the routine instead? One trick I use, when a subroutine needs the first N headers of a structure, is create an embedded 'header' structure: struct base { a b c } struct fubar1 { struct base base; x y z } struct fubar2 { struct base base; h i j } struct fubar3 { ... } callsomesubroutine(&fubar2->base); The calling direction is not the problem. It's the return value that is usually a problem. For example, a doubly-linked list function might look like this: void * getNextNode(Node *previousNode) { return(previousNode->next); } struct fubar { Node node; ... } struct fubar *fu; for (fu = getHeadOfList(&List); fu; fu = getNextNode(&fu->node)) { } There are ways around this, at least if the contents of a list is uniform. FreeBSD's kernel's /usr/src/sys/sys/queue.h implements macros for all of its list functions that actually create special node structures with previous and next pointers of exactly the proper type for however they are used. I generally use the 'void *' return value trick myself, to make the code more readable at the cost of a slight loss in type checking. But I only use it for return values... arguments are still required to be the proper exact type. -Matt To Unsubscribe: send mail to majordomo@FreeBSD.org with "unsubscribe freebsd-hackers" in the body of the message