Path: utzoo!utgpu!jarvis.csri.toronto.edu!mailrus!uunet!tut.cis.ohio-state.edu!ucsd!chem.ucsd.edu!tps From: tps@chem.ucsd.edu (Tom Stockfisch) Newsgroups: comp.lang.c Subject: Re: C's Limited Macro Capabilities Message-ID: <615@chem.ucsd.EDU> Date: 7 Dec 89 08:25:23 GMT References: <69517@psuecl.bitnet> <62664@aerospace.AERO.ORG> Reply-To: tps@chem.ucsd.edu (Tom Stockfisch) Organization: Chemistry Dept, UC San Diego Lines: 53 In article <62664@aerospace.AERO.ORG> lmiller@batcomputer.UUCP (Lawrence H. Miller) writes: >In article <69517@psuecl.bitnet> bpm@psuecl.bitnet (Brian Moquin) writes: >> #define cast(flag,x) #if flag=='I' \ >> ((int)(x)) \ >> #elif flag=='F' \ >> ((float)(x)) \ >> #endif >>This is not legal C, but if it were I think it would enhance the power > >But for each such example, you can easily write a macro that >is legal. It is not always possible to write a legal macro, at least not easily. For instance, suppose we want to define "nearest neighbors" of a lattice with periodic boundary conditions (neighbors of the edges wrap around to the other edge), and we want addressing to be very fast. int lat[DIM*DIM]; # define XNeighbor(i) # if (i)%DIM == DIM-1 ( (i) - DIM + 1 ) # else ( (i) + 1 ) # define YNeighbor(i) # if (i) >= DIM*(DIM - 1) ( (i) + DIM ) # else ( (i) - DIM*(DIM - 1) ) ... switch (s) { case 0: DoSomething( lat[XNeighbor(s)] + lat[YNeighbor(s)] ); break; case 1: DoSomething( lat[XNeighbor(s)] + lat[YNeighbor(s)] ); break; ... case DIM*DIM-1: DoSomething( lat[XNeighbor(s)] + lat[YNeighbor(s)] ); break; default: assert(0); } When I have had to do this, I simply eliminate the "#" before the "if" and the "else", and depend on the compiler to optimize out all of the branches that can't be reached (in this case, half of them), and ignore the deluge of "constant in conditional context" warnings from lint. M4 is usually of little or no help because too many C things are used in the constant arithmetic. -- || Tom Stockfisch, UCSD Chemistry tps@chem.ucsd.edu