bevan@cs.man.ac.uk (Stephen J Bevan) (05/30/90)
Some months ago, I think someone asked a question about tips on writing portable programs. Numerous people answered and a summary was produced. One suggestion was that for large projects (don't ask me to define large) a set of standards be drawn up before you start i.e. what the indentation style is, where the comments go etc. These were the sort of things I expected to see. 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) :- #define PUBLIC #define INOUT #define IN #define PRIVATE static #define FORWARD extern These would then be used in .c files to make functions look like :- PUBLIC void some_function(anInt, aChar) INOUT int *anInt; IN char aChar; { FORWARD another_function(); ... } PRIVATE void another_function(aParam) OUT int *aParam; { ... } What I'd like to know is do people acutally use this, and would they mind having to maintain code that was written this way? 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. As a final point, if you think its an ok idea, do you still think its ok if the macros were changed to lower case? (I guess the answer to this will be no, its just that I really hate UPPER CASE) Stephen J. Bevan bevan@cs.man.ac.uk
mike@hpfcso.HP.COM (Mike McNelly) (05/31/90)
> ... > 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) :- > > #define PUBLIC > #define INOUT > #define IN > #define PRIVATE static > #define FORWARD extern > > These would then be used in .c files to make functions look like :- > > PUBLIC void some_function(anInt, aChar) > INOUT int *anInt; > IN char aChar; > { > FORWARD another_function(); > ... > } > > PRIVATE void another_function(aParam) > OUT int *aParam; > { > ... > } > > What I'd like to know is do people acutally use this, and would > they mind having to maintain code that was written this way? > 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. > > As a final point, if you think its an ok idea, do you still think > its ok if the macros were changed to lower case? (I guess the > answer to this will be no, its just that I really hate UPPER CASE) > > Stephen J. Bevan This is all religion so don't be too surprised if you get diverse, argumentative responses. However, here's a personal view. We've used # ifdef DEBUGGING # define LOCAL # else /* DEBUGGING */ # define LOCAL static # endif /* DEBUGGING */ for years as a construct in our headers because it simplifies use of the symbolic debugger during development (static vars normally don't have full information in the a.out file). Personally I don't get too excited about dummy defines one way or the other but they do seem to be an attempt to provide useful information. My preference is to make all macros uppercase just so I know that they're macros and not functions (it does make a difference, of course). Some of my collegues like mixed case identifiers as a byzantine method of encoding all sorts of information (much like your dummy macros above) but this just seems to get in the way of my poor typing skills. Mike McNelly mike%hpfcla@hplabs.hp.com
robert@isgtec.UUCP (Robert A. Osborne) (06/01/90)
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. Rob. -- Robert A. Osborne ...uunet!utai!lsuc!isgtec!robert or robert@isgtec.uucp
logan@inpnms.VSE.COM (James L. Logan) (06/05/90)
In article <BEVAN.90May29182035@panda.cs.man.ac.uk> bevan@cs.man.ac.uk (Stephen J Bevan) writes: # One suggestion was that for large projects (don't ask me to define # large) a set of standards be drawn up before you start i.e. what # the indentation style is, where the comments go etc. These were # the sort of things I expected to see. Fine, unless those who decide on the style do not fit in to one of the mainstream styles. (Styles were already discussed in another c.l.c war flamefest.) What happens when the people who chose the style leave and no one knows why they're coding in a style they hate a couple of years down the road? # 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) :- # # #define PUBLIC # #define INOUT # #define IN # #define PRIVATE static # #define FORWARD extern Please don't do this. See below. # What I'd like to know is do people acutally use this, and would # they mind having to maintain code that was written this way? Yes, people do mind. In fact, it's completely annoying. # 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. They will. Please don't. As an example, the psuedo keywords "EXPORT", "IMPORT", and "PRIVATE" cannot be referenced in C programming books, manuals, etc., whereas the use of static and non-static variables and functions are described in definitive C books. They also condition the beginner programmers to look for PRIVATE/EXPORT keywords in 3rd party sources when problems arise. (As in a 3rd part database library for instance.) They simply won't find them, and will find it difficult to adjust. The psuedo keyword "EXPORT" is misleading because it is not defined in the C syntax, thus it appears as though it can be applied to any function or variable. This is not the case; take this trivial example for instance: #include <stdio.h> #include <unistd.h> int file_exists(path) char *path; { int retval; retval = access(path, F_OK); return (retval? 0: 1); } char *mkfullname(path, filename) char *path, *filename; { EXPORT char buffer[20]; sprintf(buffer, "%s/%s", path, filename); return buffer; } int main(argc, argv) int argc; char **argv; { char *fullpath; fullpath = mkfullname(argv[1], argv[2]); if (file_exists(fullpath)) { printf("You can read '%s'\n", fullpath); exit(0); } else { printf("Sorry, can't read '%s'\n", fullpath); exit(1); } /*NOTREACHED*/ } Compile it and run it with one argument being a directory and the second argument being a filename. Can you tell me why the filename prints out as garbage? Beginning to intermediate C programmers will try things in their code like I have in my example and will be unable to debug the program. Can they use a C manual to figure it out? Can they use the standards document to figure it out? They will have to view the header file to figure out what it all means. We need to make our programming environments as efficient and problem-free as possible, not pretty the C syntax up to the point where good C programmers (like a good but expensive consultant) need time to get up to speed in order to understand the code. -- James Logan UUCP: uunet!inpnms!logan Data General Telecommunications Inet: logan@rockville.dg.com (301) 590-3198
paulh@cognos.UUCP (Paul Hays) (06/05/90)
Attempts to improve C by introducing dummy identifiers are fun, but they never seem to really improve the language much, IMO. Instead, I subscribe to the well-known notion that the creativity of programmers should be curtailed wherever possible. We should direct our attention to the costly issues of sound design and thorough documentation. (Duck! Who threw that brick?) Making a local dialect detracts from one of the main advantages of C: portability of programming skills. K & R built what has proved to be a language with wide applicability. Now we have struggled through years of standard-building to arrive at a useable portable C. Let's use the standard language. I've frequently had the, er, opportunity of maintaining huge applications made with dozens of header files. Such implementations typically incorporate the 'creative' language ideas of several previous authors with varying degrees of skill. Many have usually tried to codify the sort of local standard you have described; these 'standards' always seem to come and go along with the latest manager. (Yeah, I'm a technical manager: I know whereof I speak.) How often does the maintenance programmer sit wondering what header file defines some obscure identifier and whether the current bug results from its misuse? And how often is the programmer who adds a feature to a product aware of the subtle implications of the local standard? K.I.S.S.! [The opinions expressed here are mine, not necessarily the company's.] -- Paul Hays Cognos Incorporated S-mail: P.O. Box 9707 Voice: (613) 738-1338 ext 3804 3755 Riverside Drive FAX: (613) 738-0002 Ottawa, Ontario uucp: uunet!mitel!sce!cognos!paulh CANADA K1G 3Z4
cseko@stsci.EDU (Andrew Cseko Jr.) (06/07/90)
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