Relay-Version: version B 2.10 5/3/83; site utzoo.UUCP Path: utzoo!mnetor!seismo!husc6!mit-eddie!ll-xn!ames!oliveb!sun!gorodish!guy From: guy%gorodish@Sun.COM (Guy Harris) Newsgroups: comp.lang.c Subject: Re: Writing readable code Message-ID: <22250@sun.uucp> Date: Sat, 27-Jun-87 19:45:27 EDT Article-I.D.: sun.22250 Posted: Sat Jun 27 19:45:27 1987 Date-Received: Sun, 28-Jun-87 04:53:45 EDT References: <1158@copper.TEK.COM> <6858@auspyr.UUCP> <17171@cca.CCA.COM> Sender: news@sun.uucp Lines: 93 > When I see > > if (!p) > > I read it as > > if p is not valid then ... > > The (!p) syntax tells me that p is among the class of items that may be > treated as boolean (under the C language conventions) and that we are > testing whether it is false. This is not a matter of "saving characters"; > it is a matter of classification. But what does it mean to say that a pointer is "false"? Pointers themselves really aren't Boolean; there is a boolean predicate *on* a pointer, namely the "is this pointer null" predicate. You could view the construct "p", used in a context that requires a Boolean expression, as really meaning "is_non_null(p)", and "!p" as meaning "!is_non_null(p)", or "is_null(p)". > When I see > > if (p != NULL) > > it tells me two rather different things. First of all it tells me that > p is an item for which there are one or more coded values, among which > is NULL, and that for all cases where p is not NULL, there is some action > to be taken. All of which happen to be the case for pointers. Are you arguing that "!p" is somehow better than "p != NULL"? This is a matter of taste; if you do not view "!p" as shorthand for "is_null(p)", then "p == NULL" makes more sense as a way of writing "is_null(p)", and many good programmers do not view "!p" as such a shorthand. > Secondly it tells me that the file that the statement is in > includes stdio.h (or that the author of the code is a dweeb.) And that > should tell me that the code in this file needs stdio.h, FOR I DO NOT > CONSIDER IT GOOD PROGRAMMING PRACTICE TO INCLUDE INCLUDE FILES WHICH ARE > NOT USED. OK, so either: 1) stick #define NULL 0 at the front of all modules not including 2) say "if (p == 0)" instead of "if (p == NULL)" 3) in an ANSI C implementation, stick #include at the front of your module; you *are* using at least one of the items it defines, namely NULL. Also, you didn't address the issue of if (!strcmp(str1, str2)) which I find less defensible. "strcmp" is not really boolean; it's a function from the set of strings to the set of "int"s, such that there are three predicates on the result with the following properties: strcmp(str1, str2) == 0 iff str1 == str2 strcmp(str1, str2) > 0 iff str1 > str2 strcmp(str1, str2) < 0 iff str1 < str2 (where something like "str1 == str2" refers to equality in the sense of string equality, *not* in the sense of pointer equality) and, as such, there are several predicates to be applied to the result of "strcmp" that model various predicates that can't be applied directly to strings in C. Given that, "!strcmp(str1, str2)" is "meaningful" in the sense that the semantics of C give it a meaning; however, it isn't "meaningful" in the sense that it very clearly suggests what you're testing. "!strcmp(str1, str2)" means that the two strings are equal, but someone not reading the expression carefully and just seeing the "!" might see it as testing whether they were *un*equal. If, however, there were a macro "streq", defined as #define streq(str1, str2) (strcmp(str1, str2) == 0) (we ignore the efficiency issue here, and don't stick in the recently-much-discussed optimization of comparing the first two characters) one could write "streq(str1, str2)" and it would be more clear that it was testing whether the strings were equal or not. Guy Harris {ihnp4, decvax, seismo, decwrl, ...}!sun!guy guy@sun.com