Relay-Version: version B 2.10 5/3/83; site utzoo.UUCP Path: utzoo!linus!philabs!mcnc!rti-sel!dg_rtp!throopw From: throopw@dg_rtp.UUCP (Wayne Throop) Newsgroups: net.lang.c Subject: SWAP macro Message-ID: <424@dg_rtp.UUCP> Date: Thu, 26-Jun-86 17:53:12 EDT Article-I.D.: dg_rtp.424 Posted: Thu Jun 26 17:53:12 1986 Date-Received: Fri, 27-Jun-86 05:33:07 EDT References: <1577@brl-smoke.ARPA> Lines: 93 Summary: long and picky, solution to problem at the end > Schauble@MIT-MULTICS.ARPA (Paul Schauble) > I've gotten lots of respones to my request for a form of the macro that > would make > swap(*a++, *b++); > work. Almost all of them missed the point. The swap requires a > temporary. Generating that temporary requires knowing the type. > Several of the solutions would work fine if *a and *b were int's, but I > never said that. Yes, you did say that. Your original posting gave the code fragment as: > int *a, *b; > swap (*a++,*b++); This leads to the reasonable assumption that you were talking about the case where a and b are integers. Especially when the arguments you mention have side effects, a notoriously difficult problem. I think it completely justified that readers would assume you were asking if there was any way to write a swap macro that works in the presense of side effects. In fact, I don't really see any other plausible interpretation of the original posting. > Recall the my original message was posted as a justification for a > typeof macro, akin to sizeof. I find that the need to generate > temporaries in a macro is not uncommon. Unless one is willing to do a > different version of the macro for each type, you need a way to generate > a new variable of the same type as one of the macro args. The language > provides no way to do this. True, it does not. But your original article did not mention "sizeof", nor "typeof", nor propose any extensions to C. Nor did it reference any articles that did these things. In any event, C *would* allow a macro such as swap(a,b,int) swap(c,d,struct s *) like so: #define swap(a,b,type) \ { type t;\ t=a; a=b; b=t;\ } The trick to supress side effects can also be done, if needed. #define swap(a,b,type) \ { typedef type tdtype;\ tdtype t, *pa = &(a), *pb = &(b);\ t = *pa; *pa = *pb; *pb = t;\ } or #define swap(a,b,type) \ { type t; type *pa = &(a); type *pb = &(b);\ t = *pa; *pa = *pb; *pb = t;\ } Note that these swap macros can only handle types that have no postfix operators (that is, no [] or ()). A typedef name must be supplied for such cases. Note also that the usual shortcomings of such macros apply. Lastly, the stated problem can be solved fairly portably *without* typeof. That is, a fairly portable swap macro which works even for arguments of unknown types, and works even in the presense of side-effects is possible. In vanilla C yet. #define swap(a,b) \ { char t[sizeof(a)], *pa = (char *)&(a), *pb = (char *)&(b);\ memcpy(t,pa,sizeof(a)); memcpy(pa,pb,sizeof(a));\ memcpy(pb,t,sizeof(a));\ } Limitations: - The usual problems with this macro being a bracketed construct at top level. - The usual name-hiding problems. - a and b must be the same type, and can't be register or bitfield. - It had better be legal on your machine to cast a pointer to any type you intend to swap to a pointer to character, and this cast must yield a manipulable character pointer. - Moving data of any type with character operations must yield valid data. - memcpy had better be builtin (or a macro) or this will run slower than ... well, pretty slow anyhow. You wouldn't catch *me* using this macro, but it *does* solve the stated problem, fairly portably, without resort to typeof. -- "Typeof? We don't need no steenkeen typeof!" -- Wayne Throop !mcnc!rti-sel!dg_rtp!throopw