evil@arcturus.uucp (Wade Guthrie) (08/08/90)
Gary Duzan writes: >=> char command[15]; >=> command[strlen(command)-1]=NULL; /* chop off the \n */ and Doug Gwyn says: > You're correct; the example code would happen to work with the traditional > definition of NULL as plain 0, but not if it's defined as ((void*)0). That is why I have made it a practice to define a macro: #define NULLchar '\0' in order to reduce the confusion/broken code. One thing that I find helpful is to have a header file called "global.h" or "wade.h" that has a bunch of definitions I use in all my code. This file is included by every C file and has things in it like: #define YES 1 #define NO 0 #ifdef MAIN_MODULE int my_debug = 0; #else extern int my_debug; #endif I find this to be very useful (the file is actually quite a bit bigger than this, but I don't think anyone really cares. . .) -- Wade Guthrie (evil@arcturus.UUCP) | "He gasped in terror at what sounded Rockwell International; Anaheim, CA | like a man trying to gargle while My opinions, not my employer's. | fighting off a pack of wolves" | Hitchhiker's Guide
darcy@druid.uucp (D'Arcy J.M. Cain) (08/10/90)
In article <1990Aug7.210152.7586@arcturus.uucp> evil@arcturus.uucp (Wade Guthrie) writes: >and Doug Gwyn says: >> You're correct; the example code would happen to work with the traditional >> definition of NULL as plain 0, but not if it's defined as ((void*)0). >That is why I have made it a practice to define a macro: >#define NULLchar '\0' > Can someone explain to me what is wrong with using '\0' or even 0 when a zero byte is required. Is there ever a possibility that NULLchar or whatever will evaluate to anything but a zero byte. Perhaps this is for people who get paid by the line of code. Let's see. If I was paid by the line of code ... #define IF if #define ELSE else #define LOOP_WHILE_STATEMENT_TRUE(x) while(x) #define DO_IF_STATEMENT_TRUE(x) IF(x) etc I bet I could turn "Hello, world" into a major GNU project. :-) -- D'Arcy J.M. Cain (darcy@druid) | D'Arcy Cain Consulting | MS-DOS: The Andrew Dice Clay West Hill, Ontario, Canada | of operating systems. + 416 281 6094 |
meissner@osf.org (Michael Meissner) (08/10/90)
In article <1990Aug7.210152.7586@arcturus.uucp> evil@arcturus.uucp (Wade Guthrie) writes: | Gary Duzan writes: | >=> char command[15]; | >=> command[strlen(command)-1]=NULL; /* chop off the \n */ | | and Doug Gwyn says: | > You're correct; the example code would happen to work with the traditional | > definition of NULL as plain 0, but not if it's defined as ((void*)0). | | That is why I have made it a practice to define a macro: | | #define NULLchar '\0' I really don't understand why the NULLchar macro is any clearer than just '\0'. But then, I really have never seen the need for NULL either (the appropriate cast of 0 works just as well -- if you have problems with the shift key, then maybe you should learn to type :-) -- Michael Meissner email: meissner@osf.org phone: 617-621-8861 Open Software Foundation, 11 Cambridge Center, Cambridge, MA, 02142 Do apple growers tell their kids money doesn't grow on bushes?
robert@cs.arizona.edu (Robert J. Drabek) (08/11/90)
D'Arcy J.M. Cain writes: > Wade Guthrie writes: > >I have made it a practice to define a macro: > >#define EOS '\0' > Can someone explain to me what is wrong with using '\0' or even 0 when a > zero byte is required. Perhaps this is for people who get paid by the > line of code. Nothing really `wrong' with it. I see the difference as one between using an object and using a name for the object. My personal feeling is that it is more polite to use the name. Or maybe it's like licking your lips and rubbing your stomach instead of expressing yourself in words. (Forgive me, but it's 5:30 pm and I should be heading home for dinner.) Also, EOS is easier for me to type when changing from one keyboard to another as the ', \, and 0 often vary in position and are all further from the home row. But even if I had an abbreviation set up (in vi) I'd still like to read the EOS instead. The reason why requires maybe one last explanation which is more objective. '\0' has uses and interpretations other than "end-of- string". So when I see EOS I know for certain what I meant. When I see '\0' there is the chance that some other interpretation or use is meant. -- -- Robert J. Drabek robert@cs.Arizona.EDU Department of Computer Science uunet!arizona!robert The University of Arizona 602 621 4326 Tucson, AZ 85721
skrenta@blekko.UUCP (Rich Skrenta) (08/11/90)
robert@cs.arizona.edu (Robert J. Drabek) writes: >>> #define EOS '\0' > I see the difference as one between > using an object and using a name for the object. My personal feeling is > that it is more polite to use the name. > '\0' has uses and interpretations other than "end-of- > string". So when I see EOS I know for certain what I meant. When I see > '\0' there is the chance that some other interpretation or use is meant. In many cases the object itself becomes familiar enough that it's instantly recognized. '\0' is one such object. If I saw in your code *p = EOS; I'd have to run off to your .h files to find the definition of EOS. *You* like your non-standard name for '\0', but no one else will know what it means, and it's unlikely that it will ever be a Big Win for you (like if we start terminating strings with ^A or something). Other cases occur where someone makes #defines for error strings that are used only once: #define FOO_BAR_ERROR "foo bar error" #define UNDEF_BAZ_ERR "undef baz err" I cringe when I come across code like this. Needlessly removing objects a level is distracting and gains nothing. Rich -- skrenta@blekko.commodore.com
cbp@icc.com (Chris Preston) (08/20/90)
In article <134@blekko.UUCP> skrenta@blekko.UUCP (Rich Skrenta) writes: >robert@cs.arizona.edu (Robert J. Drabek) writes: > >>>> #define EOS '\0' > >> I see the difference as one between >> using an object and using a name for the object. My personal feeling is >> that it is more polite to use the name. > >> '\0' has uses and interpretations other than "end-of- >> string". So when I see EOS I know for certain what I meant. When I see >> '\0' there is the chance that some other interpretation or use is meant. > >In many cases the object itself becomes familiar enough that it's >instantly recognized. '\0' is one such object. If I saw in your >code > > *p = EOS; > >I'd have to run off to your .h files to find the definition of EOS. Perhaps a comment in an appropriate place might alleviate this. >*You* like your non-standard name for '\0', but no one else will >know what it means, and it's unlikely that it will ever be a Big Win >for you (like if we start terminating strings with ^A or something). Then, it will be a very big win. Using two characters would break much more software than would changing the terminator to a single different letter. In the case of doing a sprinkling of assembly on DOS or CPM, the $ is used as a terminator (typically) when calling an interrupt service routine. If you are doing assembly calls in a section of code you need only #if DOS #undef EOS #define EOS '$' #endif for ( this=that; someloop<ArraySize && etc; someloop++) if (someloop=ArraySize-1){ (*array)[someloop]=EOS; CallToAssembly(*array); }else DoSomethingElse((*array)[someloop]); #if DOS #undef EOS #define EOS '\0' #endif Typically, one could even replace '$' and '\0' further with DOS_CPM_TERMINATOR and UNIX_DOS_C_CALL_TERMINATOR. So, while you as a Unix or Dos or whatever programmer might not care about the others, it allows a level of abstraction that facilitates portability and maintainability. Mind you, I might like shorter labels, but one get's the idea. > >Other cases occur where someone makes #defines for error strings >that are used only once: > >#define FOO_BAR_ERROR "foo bar error" >#define UNDEF_BAZ_ERR "undef baz err" > >I cringe when I come across code like this. Needlessly removing objects >a level is distracting and gains nothing. It seems here that if FOO_BAR_ERROR is something along the lines of #define DATACOM_NOT_INIT "Datacomm was not initialized" might be usefull. One could then modify this like so: #if MSDOS #define DATACOM_NOT_INIT "Execute datacomm.exe and restart the program" #elif SYSV #define DATACOM_NOT_INIT "Contact you system administrator for datacomm startup" #elif BTOS #define DATACOM_NOT_INIT "Master Cluster datacomm not initialized" #else #define DATACOM_NOT_INIT "Datacomm is not initailized" #endif Now, which is more 1)Cost effective 2)Maintainable ergo 3)Good programming style? To go through and have to change this message every time you port the code, or allow for changes without having to modify the code beyond considering operational differences because your macros cover most of the bases? In fact, there are few instances in which text strings and constants should not be removed to a macro level (IMHO, mind you, IMHO). To do so means that the programmer will need to know where the pertinent substitutions are located, and the programmer should insure that all labels are clear in their intent. IMHO this just means that good programming requires more work up front and less work later on, but that is the tradeoff between development and maintenance. It also impacts on the reusability of code. Pay me now or pay me later. > >Rich >-- >skrenta@blekko.commodore.com cbp cbp@icc.com
henry@zoo.toronto.edu (Henry Spencer) (08/20/90)
In article <1990Aug20.000227.12867@icc.com> cbp@icc.com (Chris Preston) writes: >>In many cases the object itself becomes familiar enough that it's >>instantly recognized. '\0' is one such object. If I saw in your >>code >> >> *p = EOS; >> >>I'd have to run off to your .h files to find the definition of EOS. > > Perhaps a comment in an appropriate place might alleviate this. Comments are not a substitute for using familiar practices instead of unfamiliar ones. Familiar ones should be preferred unless there is a *substantial* advantage to be had. I don't see one here. -- Committees do harm merely by existing. | Henry Spencer at U of Toronto Zoology -Freeman Dyson | henry@zoo.toronto.edu utzoo!henry
ok@goanna.cs.rmit.oz.au (Richard A. O'Keefe) (08/20/90)
In article <1990Aug20.000227.12867@icc.com>, cbp@icc.com (Chris Preston) writes: (quoting a quote) > >Other cases occur where someone makes #defines for error strings > >that are used only once: > >#define FOO_BAR_ERROR "foo bar error" > >#define UNDEF_BAZ_ERR "undef baz err" > > > >I cringe when I come across code like this. Needlessly removing objects > >a level is distracting and gains nothing. and then defends this, where there are conditional definitions. He suggests > #if MSDOS > #define DATACOM_NOT_INIT "Execute datacomm.exe and restart the program" > #elif SYSV > #define DATACOM_NOT_INIT "Contact you system administrator for datacomm startup" > #elif BTOS > #define DATACOM_NOT_INIT "Master Cluster datacomm not initialized" > #else > #define DATACOM_NOT_INIT "Datacomm is not initailized" > #endif as an example of a Good Thing. I cringe when I see code like this too. For why? Internationalisation, _that's_ for why. > It also impacts on the reusability of code. Pay me now or pay me later. Considering the large negative impact on internationalisation of having fixed strings in the program, may we _bill_ him, I wonder? A very simple way of making a "resource file" in UNIX is this: cat >resource.awk <<'end_of_file.' BEGIN { pos = 0 max = 0 } { print "#define", $1, (pos + length($1) + 1) "L" pos += length + 1 # for MS-DOS, use + 2 l = length - length($1) - 1 if (l > max) max = l filename = FILENAME } END { print "#define res__file \"" filename "\"" print "#define res__max " max } end_of_file. cat >resource.c <<'end_of_file.' #include <stdio.h> #include "resource.h" char *rescpy(dst, dstlen, offset) char *dst; int dstlen; long offset; { FILE *resfile; char buffer[res__max+1]; int ok; resfile = fopen(res__file, "r"); if (!resfile) return NULL; ok = fseek(resfile, offset, 0) == 0 && fgets(dst, dstlen, resfile) != NULL; fclose(resfile); return ok ? dst : NULL; } void reserr(offset) long offset; { char buffer[512]; if (rescpy(buffer, sizeof buffer, offset)) fprintf(stderr, "%s", buffer); else fprintf(stderr, "Unknown error (%ldL)\n", offset); } end_of_file. This takes a resource file made up of lines <message name> <TAB> <message text> If you do awk -f resource.awk resourcefile >resource.h and then cc -c resource.c you get a header file defining the <message name>s to be the appropriate offsets in the resource file, and then rescpy(buffer, sizeof buffer, MessageName) with arguments rather like fgets() will give you a copy of the message, and reserr(MessageName) will write the message to stderr. The bottom line is that you can just make a whole bunch of files resource.uk resource.us resource.fr resource.dk and so on, then awk -f resource.awk resource.$LANG >resource.h and re'make'ing your program will let you adapt to a different language. (I used awk here to keep this posting short. It would be better to make the header file with a C program so that you could use ftell() to get exactly the right values to give to fseek().) Of course, if you are using CMS, or VMS, or SVR4, or something with the X/Open "nls" routines, you could use those. Unfortunately, none of these interfaces is portable. A crude and limited hack like the one above may have a (near term) place in writing code portable between these systems. This code is free. Free code is worth what you pay for it. -- The taxonomy of Pleistocene equids is in a state of confusion.
ergo@netcom.UUCP (Isaac Rabinovitch) (08/20/90)
In <1990Aug20.073554.9537@zoo.toronto.edu> henry@zoo.toronto.edu (Henry Spencer) writes: >>>In many cases the object itself becomes familiar enough that it's >>>instantly recognized. '\0' is one such object. If I saw in your >>>code >>> >>> *p = EOS; >>> >>>I'd have to run off to your .h files to find the definition of EOS. >> >> Perhaps a comment in an appropriate place might alleviate this. >Comments are not a substitute for using familiar practices instead of >unfamiliar ones. Familiar ones should be preferred unless there is >a *substantial* advantage to be had. I don't see one here. I agree with you in principle, and also in this instance (does anyone seriously intend to put a comment at every end-of-string comparison?). The problem is with the concept of "familiar". This business of strings always terminating with a null is fundamental to C programming -- if you don't know that '\0' means "end-of-string" then you simply don't know how C strings work at all! (Note that nobody ever uses an (int) 0 in place of '\0', even though the two are equivalent!) On the other hand, you can say (and I used to) that using 1 and 0 instead of TRUE and FALSE is a similar "familiar practice", since any competant C programmer knows that C booleans are just integers. In this case it probably makes a big difference that TRUE and FALSE are ordinary English words, not obscure acronyms. I recently came up against a similar clash of "familiar concepts" in C. People were arguing (was it in this group?) over why programmers use "i" instead of "i == 0". I asserted that this shorter expression usually generated tighter code, at least on stupider compilers. I think I might have been right about this 10 years ago, but even if I was I'd only shown I was out of date in the current state of compiler writing. I got one private message from a guy at a certain Big Software Company who told me that reducing such comparisons was the first optimization any compiler writer implemented. True enough, but what I found especially interesting was all the public and private flames fired at me by folks who insisted not just that I was wrong (which, of course, I was) but that the C language was *defined* to include such a reduction! -- ergo@netcom.uucp Isaac Rabinovitch atina!pyramid!apple!netcom!ergo Silicon Valley, CA uunet!mimsy!ames!claris!netcom!ergo Disclaimer: I am what I am, and that's all what I am!
chip@tct.uucp (Chip Salzenberg) (08/21/90)
According to cbp@icc.com (Chris Preston): >In article <134@blekko.UUCP> skrenta@blekko.UUCP (Rich Skrenta) writes: >>*You* like your non-standard name for '\0', but no one else will >>know what it means, and it's unlikely that it will ever be a Big Win >>for you (like if we start terminating strings with ^A or something). > >Then, it will be a very big win. Yes, but it will never happen. I'm sure that Rich just forgot the smiley. Remember that '\0'-terminated strings are a part of the C language. Get rid of them, and you don't have C any more. It is obvious that most magic numbers should be removed to macro definitions. However, '\0' isn't one of them; it will NEVER change. Not as long as you're programming in C, anyway... -- Chip Salzenberg at Teltronics/TCT <chip@tct.uucp>, <uunet!pdn!tct!chip>
cbp@icc.com (Chris Preston) (08/21/90)
From article <3585@goanna.cs.rmit.oz.au>, by ok@goanna.cs.rmit.oz.au (Richard A. O'Keefe): > In article <1990Aug20.000227.12867@icc.com>, cbp@icc.com (Chris Preston) writes: > (quoting a quote) >> >Other cases occur where someone makes #defines for error strings >> >that are used only once: > >> >#define FOO_BAR_ERROR "foo bar error" >> >#define UNDEF_BAZ_ERR "undef baz err" >> > >> >I cringe when I come across code like this. Needlessly removing objects >> >a level is distracting and gains nothing. > > and then defends this, where there are conditional definitions. > He suggests >> #if MSDOS >> #define DATACOM_NOT_INIT "Execute datacomm.exe and restart the program" >> #elif SYSV >> #define DATACOM_NOT_INIT "Contact you system administrator for datacomm startup" and I said etc, etc. > as an example of a Good Thing. I cringe when I see code like this too. No, an example of separating abstraction through the use of lables. > For why? Internationalisation, _that's_ for why. Hm, now we go to a different level. Probably a good point. >> It also impacts on the reusability of code. Pay me now or pay me later. > > Considering the large negative impact on internationalisation of having > fixed strings in the program, may we _bill_ him, I wonder? We is out of context, and no, you may not. > > A very simple way of making a "resource file" in UNIX is this: deleted. > > The bottom line is that you can just make a whole bunch of files > resource.uk > resource.us > resource.fr > resource.dk > and so on, then > awk -f resource.awk resource.$LANG >resource.h > and re'make'ing your program will let you adapt to a different language. > > (I used awk here to keep this posting short. It would be better to make > the header file with a C program so that you could use ftell() to get > exactly the right values to give to fseek().) Sure, and if one does this in System V one could just push a streams module on top of the line discipline and let all applications work in the chosen language. Quick, neat and available. But we digress into issues of O/S rapidly here. At this point someone politely suggests that the newsgroup and its O/S independence is worth considering. In that spirit, I would like to return to the actual issue (as noted in the subject line, though I was guilty of diverging from it ). I have been thinking more on the EOS issue, and since it would break lots of things were someone to do this in other than special cases (like, breaking all string functions is rude, don't you think?), means that I was wrong in suggestion labeling '\0' in anything other than itself is a good idea. Retraction is hereby submitted. Better not to touch that which is so basic to the language itself. There is no clearly important benefit in allowing for a change of such an unlikely nature. Basta, finito. cbp cbp@icc.com --------- That is twice in one day --al, don't let it get to you. --------- Of course, these are opinions.
rmj@tcom.stc.co.uk (Rhodri James) (08/21/90)
In article <3585@goanna.cs.rmit.oz.au> ok@goanna.cs.rmit.oz.au (Richard A. O'Keefe) writes: }In article <1990Aug20.000227.12867@icc.com>, cbp@icc.com (Chris Preston) writes: }(quoting a quote) }> >#define FOO_BAR_ERROR "foo bar error" }> >#define UNDEF_BAZ_ERR "undef baz err" }> > }> >I cringe when I come across code like this. Needlessly removing objects }> >a level is distracting and gains nothing. } }and then defends this, where there are conditional definitions. }> #if MSDOS }> #define DATACOM_NOT_INIT "Execute datacomm.exe and restart the program" }> #elif SYSV [etc] }as an example of a Good Thing. I cringe when I see code like this too. }For why? Internationalisation, _that's_ for why. I cringe when I see this (unwords like "internationalisation", I mean). I take it that by that you mean converting strings in code to foreign languages ("an act of making something international", as if it did any such thing). Also I fail to see your point. Surely such #ifdef switching as above is more efficient, simpler to maintain and more legible than the scrabbling about with resource files you prefer? I know which I would rather do of running pre-preprocessing or just compiling with "-DFRENCH". }> It also impacts on the reusability of code. Pay me now or pay me later. } }Considering the large negative impact on internationalisation of having }fixed strings in the program, may we _bill_ him, I wonder? Demonstrate to me a negative impact on internationalisation (ugh) and I might believe you. Any negative impact will do, I'm not too choosy. -- * Windsinger * "Nothing is forgotten..." * rmj@islay.tcom.stc.co.uk * Mike Whitaker * or (occasionally) * "...except sometimes the words" * rmj10@phx.cam.ac.uk * Phil Allcock
chris@mimsy.umd.edu (Chris Torek) (08/22/90)
>In article <3585@goanna.cs.rmit.oz.au> ok@goanna.cs.rmit.oz.au (Richard A. O'Keefe) recommends against `#define'ing error strings and recommends instead, e.g., reading them from a file: >>For why? Internationalisation, _that's_ for why. In article <1881@jura.tcom.stc.co.uk> rmj@tcom.stc.co.uk (Rhodri James) writes: >I cringe when I see this (unwords like "internationalisation", I mean). Well, I am not particularly enamoured of polysyllabic neologisms applied epideictically myself. :-) But I evagate: >I take it that by that you mean converting strings in code to foreign >languages ("an act of making something international", as if it did any >such thing). Also I fail to see your point. Surely such #ifdef switching >as above is more efficient, simpler to maintain and more legible than >the scrabbling about with resource files you prefer? Efficient? Probably so---but we are talking about an error handler here. (`My code handles 100,000 errors per second! Of course it only handles 10 non-errors per second....') Simpler to maintain? Perhaps. More legible? Not really; maybe even not at all: >I know which I would rather do of running pre-preprocessing or just >compiling with "-DFRENCH". I do not understand why these are listed as the alternatives (what `running pre-processing'?). But given modern networks and systems, it is not only possible, it is even likely that the same machine will be used simultaneously from Japan, the USA, France, and Germany, and the same utility (a single binary compiled in the UK) may have to produce the same error message in four different languages, all at the same time, with one of them in a 16-bit character set. This is rather difficult to accomodate cleanly in the source--- particularly if one is called upon to add a new language every day (for a week or two, then every few days, and eventually only one a year or so). -- In-Real-Life: Chris Torek, Univ of MD Comp Sci Dept (+1 301 405 2750) Domain: chris@cs.umd.edu Path: uunet!mimsy!chris
cuuee@warwick.ac.uk (Sean Legassick) (08/24/90)
In article <1990Aug20.000227.12867@icc.com> cbp@icc.com (Chris Preston) writes: [quoting a quote] >>*You* like your non-standard name for '\0', but no one else will >>know what it means, and it's unlikely that it will ever be a Big Win >>for you (like if we start terminating strings with ^A or something). > > Then, it will be a very big win. Using two characters would break > much more software than would changing the terminator to a single > different letter. In the case of doing a sprinkling of assembly > on DOS or CPM, the $ is used as a terminator (typically) when calling an > interrupt service routine. If you are doing assembly calls in a section > of code you need only > [code omitted] > > Typically, one could even replace '$' and '\0' further with > DOS_CPM_TERMINATOR and UNIX_DOS_C_CALL_TERMINATOR. So, while you as > a Unix or Dos or whatever programmer might not care about the others, it > allows a level of abstraction that facilitates portability and > maintainability. > > > Mind you, I might like shorter labels, but one get's the idea. > Very clever, but it hardly solves the problem of different string representations - consider Pascal. It has not terminator, strings start with a count. No amount of #defining will solve that. --------------------------------------------------------------------------- Sean Legassick, cuuee@uk.ac.warwick.cu "Man, I'm so hip I find it Computing Services (the walking difficult to see over University of Warwick C obfuscator!) my pelvis" - D Adams