Path: utzoo!attcan!uunet!cs.utexas.edu!asuvax!noao!stsci!cseko From: cseko@stsci.EDU (Andrew Cseko Jr.) Newsgroups: comp.lang.c Subject: Re: portability/maintenance Message-ID: <1509@shapley.stsci.edu> Date: 7 Jun 90 14:08:00 GMT References: <470@isgtec.UUCP> Organization: Space Telescope Science Institute, Baltimore, MD 21218 Lines: 144 From article <470@isgtec.UUCP>, by robert@isgtec.UUCP (Robert A. Osborne): > bevan@cs.man.ac.uk (Stephen J Bevan) writes: >>Another suggestion, however, was to use dummy macros to help make >>the type and purpose of parameters and functions stand out. For >>example, you would have a header file containing the following >>sort of definitions (the rest of this is in K&R I C, I haven't >>really got into the swing of ANSI C yet) :- > The biggest problem with these macros is that they are conventions, not > syntactical necessities. Therefore they can be wrong in which case > they are worse (far worse) than vanilla C. Another problem is that > they try and hide language functionality; I know what a static function > declaration *IS*; when I see PRIVATE or local or some such I immediately > have to look for what it *IS*. If you can write C code cleanly > in legible fashion (like I can :-), these macros just get in the way; > if you can't write code cleanly the greatest macro package in the world > isn't going to help. > >>What I'd like to know is do people actually use this, and would >>they mind having to maintain code that was written this way? > I would probably pass it through sed to get rid of these macros. > I would HATE to maintain this style of code. > >>I've got to admit I kind of like the idea, but if people are going >>to bitch about the code if its written in this style, then I'd >>rather not use it. > The problem is (as we have seen before in this group) that everybody > has their own "favourite macros" and hates any other macro set. > It's best not to use them at all. In an issue as "religous" as this the burden of correct implementation really falls on the implementor. My own concerns would be that the person neither go "overboard" or "underboard". By "overboard" I mean they don't use a MACRO to document something that is all ready obvious, for instance '#define PTR_OF(a) &(a)'. In the above example the difference between '#define INOUT' and a comment like '/* IN/OUT */' is not clear to me. And "underboard" means that if you create a macros to document code then use them consistently throughout the program and not just when you 'feel like it'. In my own development I do use macros to hide code that 1) I do not want to see once its implemented and 2) do not want to hand type every place I need it. My prime example is the implemenation of a vector where the type can be float, int, unsigned short etc. I have two types COORD and INDEX defined something like this: typedef struct { . . . struct { U_SHORT ndims; float val[4]; } public; . . . } COORD; typedef struct { . . . struct { unsigned short ndims; int val[4]; } public; . . . } INDEX; I wanted to be able to reference both val arrays without having to always type 'public.val[ i ]'. And from a philosophical perspective I wanted to communicate something like "get/set the i'th dimension of the vector". My solution was the following macros #define get_dim( P, i ) (P)->public.val[ i ] #define set_dim( P, i, v ) (P)->public.val[ i ] = v which makes them look like overdefined function in object oriented languages. They work for any type (of course, only if the structure is defined the same way) and the compiler will do proper type conversion of 'v' to the type of the val[] array. This was my first pass. I then realized that without changing any code I've already written that used these macros I could include debug checks. I wanted to verify that 1) index i was less than the dimensionality of the vector, 2) if I was 'getting' the value - it had already been set somewhere else and 3) at run-time be able to turn off the debugging. My macros then became something like the following. #define get_dim( P, i ) \ if (debug_level > 50) \ { \ ... code to check i < ndims .. \ ... code to check value already set ... \ } \ (P)->public.val[ i ] #define set_dim( P, i, v ) \ if (debug_level > 50) \ { \ ... code to check i < ndims .. \ } \ (P)->public.val[ i ] = v I also wanted to exclude all the debugging code from the production version of the executable. My macros definitions became #if DEBUGGING #define get_dim( P, i ) \ if (debug_level > 50) \ { \ ... code to check i < ndims .. \ ... code to check value already set ... \ } \ (P)->public.val[ i ] #else #define get_dim( P, i ) (P)->public.val[ i ] #endif #if DEBUGGING #define set_dim( P, i, v ) \ if (debug_level > 50) \ { \ ... code to check i < ndims .. \ } \ (P)->public.val[ i ] = v #else #define set_dim( P, i, v ) (P)->public.val[ i ] = v #endif I'm curious about anybody elses experience in using CPP this way? andrew cseko@stsci.edu If 'all the world is a stage' then whose the audience? - me, myself & I