Date: Wed, 21 Feb 2001 11:23:32 -0800 (PST) From: Matt Dillon <dillon@earth.backplane.com> To: "Jacques A. Vidrine" <n@nectar.com> Cc: freebsd-hackers@FreeBSD.ORG Subject: Re: portability sanity check Message-ID: <200102211923.f1LJNWl24375@earth.backplane.com> References: <20010221094228.A93221@hamlet.nectar.com>
next in thread | previous in thread | raw e-mail | index | archive | help
: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
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?200102211923.f1LJNWl24375>