Path: csiph.com!x330-a1.tempe.blueboxinc.net!newsfeed.hal-mli.net!feeder1.hal-mli.net!border3.nntp.dca.giganews.com!Xl.tags.giganews.com!border1.nntp.dca.giganews.com!nntp.giganews.com!local2.nntp.dca.giganews.com!nntp.earthlink.com!news.earthlink.com.POSTED!not-for-mail NNTP-Posting-Date: Tue, 20 Sep 2011 22:10:27 -0500 Message-ID: <4E7955A1.440D@mindspring.com> Date: Tue, 20 Sep 2011 23:10:25 -0400 From: pete Reply-To: pfiland@mindspring.com Organization: PF X-Mailer: Mozilla 3.04Gold (WinNT; I) MIME-Version: 1.0 Newsgroups: comp.lang.c Subject: Re: evaluate a generic swap function References: <640a6fdc-0001-4de0-ba3d-d7ab5abcdc69@z18g2000yqb.googlegroups.com> Content-Type: text/plain; charset=us-ascii Content-Transfer-Encoding: 7bit Lines: 93 X-Usenet-Provider: http://www.giganews.com NNTP-Posting-Host: 4.156.228.31 X-Trace: sv3-IjivL30pxgBKNfCUQ29BQXK48BU2LAAlOe4ZzE8IYRcKnfj1h1nMN/2wHrUUlfXkTRqV24hedmc8j27!gaZS0Hnf5uwzWF+MyYdGc3SNosQ/YvtB2IW4ca1Uqo6/0wAJrCAai31mqzuSfjAf99wPbYKRI9DL!6dIWeVPiSA== X-Abuse-and-DMCA-Info: Please be sure to forward a copy of ALL headers X-Abuse-and-DMCA-Info: Otherwise we will be unable to process your complaint properly X-Postfilter: 1.3.40 X-Original-Bytes: 4635 Xref: x330-a1.tempe.blueboxinc.net comp.lang.c:10626 ImpalerCore wrote: > > On Sep 20, 10:33 am, Malcolm McLean > wrote: > > On Sep 20, 4:51 pm, Stanley Rice wrote:> Hello all > > > > > I wrote a "generic" swap function, which can swap some type, such as > > > int, double, long. But I don't know how to evaluate this function, and > > > don't know whether it's a good idea to use such a function. I hope you > > > can give me some suggestions. > > > > The function calls malloc to allocate a temporary buffer. This means > > that it's vulnerable to failure. It's also likely to be inefficient. > > > > You can write swap() as a byte swapping loop, which avoids the need > > for a malloc(). The problem is that most calls will be to arrays of > > ints or other larger types. You can probably get a 4x speed up if you > > know that data is a multiple of four and aligned. > > What this means is that swap() is really a function, like memcpy, best > > implemented by the compiler, which can apply patches to speed up > > common cases. E.g. swapping two basic types, which is an obvious use > > for the function, can be turned into a sequence of three > > instructions, or even sometimes eliminated altogether. > > One method to consider is to write macros to declare the function > prototype and definition of a swap specialized to the type. > > \code snippet > #define C_SWAP_PROTO( NAME, TYPE ) void c_swap_##NAME( TYPE* left, > TYPE* right ) > > #define C_SWAP_IMPL( NAME, TYPE ) \ > void c_swap_##NAME( TYPE* left, TYPE* right ) \ > { \ > TYPE tmp; \ > \ > tmp = *left; \ > *left = *right; \ > *right = tmp; \ > } > \endcode > > Then, if one wants to swap a particular type, they declare the > prototype and definition where needed and use the generated function > name to swap the objects. The advantage is that in a library setting, > one can create a generic template for a swap without the need to > maintain an arbitrary list of swap functions, like c_swap_int, > c_swap_long, c_swap_my_struct, etc. > > The reason for the 'NAME' attribute is that types with spaces in them > obviously cause problems in the function prototypes. You could use > them like the following. > > \code snippet > #include > #include > > C_SWAP_PROTO( uint, unsigned int ); > > int main( void ) > { > unsigned int u1 = 10; > unsigned int u2 = 20; > > c_swap_uint( &u1, &u2 ); > > printf( "[u1,u2] = [%u,%u]\n", u1, u2 ); > > return EXIT_SUCCESS; > } > > /* Important to *not* add the semicolon after the IMPL macro */ > C_SWAP_IMPL( uint, unsigned int ) > \endcode > > I fully acknowledge that some may consider this "function template" a > coding horror. But at the same time, I have found this kind of setup > very convenient from a maintenance perspective. I use these macros: #define SWAP(N, A, B, T) \ (MOV##N((T), (A)), MOV##N((A), (B)), MOV##N((B), (T))) #define MOVi(A, B) ((void)(*(A) = *(B))) #define MOVa(A, B) ((void)memcpy((A), (B), sizeof *(A))) MOVa is for when *(A) is of array type. MOVi is for when *(A) isn't of array type. -- pete