Path: utzoo!attcan!uunet!cs.utexas.edu!husc6!think!bloom-beacon!envy.pika.mit.edu!scs From: scs@envy.pika.mit.edu (Steve Summit) Newsgroups: comp.lang.c Subject: Re: best way to return (char *) Message-ID: <12364@bloom-beacon.MIT.EDU> Date: 1 Jul 89 21:32:03 GMT References: <7800013@gistdev> Sender: daemon@bloom-beacon.MIT.EDU Reply-To: scs@adam.pika.mit.edu (Steve Summit) Lines: 71 In article <7800013@gistdev> joe@gistdev.UUCP lists several common ways of implementing routines which return strings. One technique I haven't seen mentioned is to implement a routine which returns a pointer to not one, but to one of several static areas. A perfect example is a routine which generates a string representation of an internal encoding, for use when generating human-readable printouts. For instance, in a C language processor, an error must be generated when two types are incompatible for a binary or casting operator. I have used code like the following: extern char *printtype(struct type *); extern void error(char *, ...); /* cast rhs to type of lhs, before assignment */ if(rhs->type incompatible with lhs->type) { error("can't assign %s to %s", printtype(rhs->type), printtype(lhs->type)); return ERROR; } cast(rhs, lhs->type); /* now do assignment... */ where printtype takes an internal structure describing a C type and returns a string like "pointer to function returning int". The code for printtype() looks something like #define NRETBUF 3 #define MAXLEN 100 char * printtype(type) struct type type; { static char retbufs[NRETBUF][MAXLEN]; static int retbufi = 0; char *retbuf; retbuf = retbufs[retbufi]; /* build descriptive string in retbuf */ retbufi = (retbufi + 1) % NRETBUF; return retbuf; } I agree with previous posters that general-purpose routines should dynamically allocate the returned buffer, deallocation difficulties notwithstanding. For little special-purpose utility routines, however, such as the output format helper above, any handling of return buffer allocation by the caller would be inconvenient (and might therefore make it less likely that good error messages would be generated). The multiple return buffer trick is useful in these cases, since they are often the ones (i.e. multiple calls within one printf) where the overwriting of a single buffer would be a problem. (Circumloqutions like error("can't assign %s ", printtype(rhs->type)); error(" to %s", printtype(lhs->type)); are ugly, and don't work well if the error routine adds file or line number information with each invocation.) Steve Summit scs@adam.pika.mit.edu