Prev: integer
Next: shared memory question
From: Keith Thompson on 25 Feb 2010 12:15 John Bode <jfbode1029(a)gmail.com> writes: [...] > The all-caps convention makes it easier to distinguish preprocessor > macros from other symbols. This can matter, especially when using > function-like macros (macros that take arguments). Remember that > macro expansions are simple text substitutions; a macro like > > #define square(x) (x*x) > > does not compute "x*x" and return a value; it *replaces* the text > "square(x)" with "(x*x)". If x is "z++", then the replacement text is > "(z++*z++)", which invokes undefined behavior. If x is "a+b", then > the replacement text is "(a+b*a+b)". By using all-uppercase for > macros, it makes it easier to see potential red flags like "SQUARE(x+ > +)" or "SQUARE(x+y)". [...] The side effect problem can't be solved (or at least can't be easily solved) if you're using a macro, but the operator precedence problem can. #define SQUARE(x) ((x)*(x)) You need to parenthesize the entire definition *and* each reference to the parameter(s). BTW, here's my favorite example of preprocessor abuse: #include <stdio.h> #define SIX 1+5 #define NINE 8+1 int main(void) { printf("%d * %d = %d\n", SIX, NINE, SIX * NINE); return 0; } -- Keith Thompson (The_Other_Keith) kst-u(a)mib.org <http://www.ghoti.net/~kst> Nokia "We must do something. This is something. Therefore, we must do this." -- Antony Jay and Jonathan Lynn, "Yes Minister"
From: Scott Lurndal on 25 Feb 2010 13:12 Lorenzo Villari <vlllnz(a)tiscali.it> writes: >On 24 Feb 2010 22:09:43 GMT >scott(a)slp53.sl.home (Scott Lurndal) wrote: > >> >> if (condition) { >> >> is preferred over >> >> if (condition) >> { >> >> Makes it much more likely that a properly written function will fit >> on a single page/screen. > >Hmmm... > >if (condition) { <-- one line > >if (condition) <-- one line >{ <-- and another one, makes two lines > >Does that really make a BIG difference? On a 24-line screen, you betcha. scott
From: Scott Lurndal on 25 Feb 2010 13:18 Ian Collins <ian-news(a)hotmail.com> writes: >Scott Lurndal wrote: >> James Harris <james.harris.1(a)googlemail.com> writes: >>> On 24 Feb, 20:53, BruceS <bruce...(a)hotmail.com> wrote: >>> >>> ... >>> >>>> I would like to add that, as long as you're trying to use good style, >>>> for God's sake don't use the wrong indentation style. =A0If you put your >>>> opening braces on the same line as your conditional, you'll just look >>>> like a fool in front of your friends and colleagues. >>> Snobbish nonsense! >>> >>> >> >> Indeed. >> >> if (condition) { >> >> is preferred over >> >> if (condition) >> { > >By whom? > >> Makes it much more likely that a properly written function will fit on a single >> page/screen. > >If the extra lines required for an opening brace are an issue, the >function isn't properly written! > >> In 30 years of C programming, no employer or project has used the latter form. > >I can honestly negate that line. Ken and Dennis started the trend, and all my employers (operating system vendors) have followed it. This fragment is from c00.c (the Unix V6 C compiler (note the obsolete =& operator!)): /* * Search the keyword table. * Ignore initial "." to avoid member-of-structure * problems. */ findkw() { register struct kwtab *kp; register char *p1, *p2; char *wp; int firstc; wp = symbuf; firstc = *wp; *wp =& 0177; for (kp=kwtab; (p2 = kp->kwname); kp++) { p1 = wp; while (*p1 == *p2++) if (*p1++ == '\0') { cval = kp->kwval; return(1); } } *wp = firstc; return(0); } scott
From: Rainer Weikusat on 25 Feb 2010 14:37 Keith Thompson <kst-u(a)mib.org> writes: > Rainer Weikusat <rweikusat(a)mssgmbh.com> writes: >> Keith Thompson <kst-u(a)mib.org> writes: >>> Rainer Weikusat <rweikusat(a)mssgmbh.com> writes: >>>> Poster Matt <postermatt(a)no_spam_for_me.org> writes: >>> [...] >>>>> 4. Does anyone care where the pointer * is? I prefer keeping to next >>>>> to the type, rather than next to the variable name. >>>>> >>>>> EG. I like: char* firstName; and not so much: char *firstName; >>>> >>>> C knows about three kinds of derived types, arrays >>>> >>>> char a[]; >>>> >>>> Pointers to functions >>>> >>>> char (*a)(); >>>> >>>> and pointers >>>> >>>> char *a; >>> >>> Array types, structure types, union types, function types, and pointer >>> types are all derived types (C99 6.2.5). >> >> Exercise for the reader: Which of the six types defined above are >> irrelevant for this statement about 'declaration of derived types' >> because they belong to a different syntactical class than the three >> examples? Which type is irrelevant because it cannot directly appear >> in a variable declaration? Which other class of types should appear >> instead because they can? > > You said that "C knows about three kinds of derived types". In fact, > there are six. I was disputing the accuracy of your statement, not > its relevance. Given that these three kinds of derived types exist, my statement was accurate. I didn't claim that there weren't any other derived types, I just didn't write about them because they were irrelvant for the statement I intended to make (this is, of course, just the same kind of pointless nitpicking). [...] >>> But it might be acceptable to special-case on some cases *with* >>> an understanding of the C type system. I prefer "char *a;" myself, >>> but there's a valid argument that "char* a;" makes it more obvious >>> that's meant (that a is of type char*). >> >> A type 'char*' doesn't exist. A type named 'char' does, and assuming >> that T names an existing type, an object can be declared as 'pointer >> to a T' by using the syntax >> >> T *o; >> >> 'Pointerness' is an attribute of the object, not of the type. This is >> also consistent with the original intention behind this syntax, namely >> that 'declaration should resemble use'. > > Wrong. char* is a type. Specifically, it's a derived type and a > pointer type. See C99 6.2.5, particularly paragraph 20. T *o; is a pointer declarator and it means that the type of o is 'pointer to T', not 'T*' (6.7.5.1|1). [...] > (And for the record, I agree that "T *o;" is preferable to > "T* o;"; I just don't agree that it's a huge deal.) It's a pointless inconsistency.
From: Keith Thompson on 25 Feb 2010 14:57
Rainer Weikusat <rweikusat(a)mssgmbh.com> writes: > Keith Thompson <kst-u(a)mib.org> writes: >> Rainer Weikusat <rweikusat(a)mssgmbh.com> writes: >>> Keith Thompson <kst-u(a)mib.org> writes: >>>> Rainer Weikusat <rweikusat(a)mssgmbh.com> writes: [...] >>>>> C knows about three kinds of derived types, arrays >>>>> >>>>> char a[]; >>>>> >>>>> Pointers to functions >>>>> >>>>> char (*a)(); >>>>> >>>>> and pointers >>>>> >>>>> char *a; >>>> >>>> Array types, structure types, union types, function types, and pointer >>>> types are all derived types (C99 6.2.5). >>> >>> Exercise for the reader: Which of the six types defined above are >>> irrelevant for this statement about 'declaration of derived types' >>> because they belong to a different syntactical class than the three >>> examples? Which type is irrelevant because it cannot directly appear >>> in a variable declaration? Which other class of types should appear >>> instead because they can? >> >> You said that "C knows about three kinds of derived types". In fact, >> there are six. I was disputing the accuracy of your statement, not >> its relevance. > > Given that these three kinds of derived types exist, my statement was > accurate. I didn't claim that there weren't any other derived types, I > just didn't write about them because they were irrelvant for the > statement I intended to make (this is, of course, just the same kind > of pointless nitpicking). Ok. I read your statement as implying that C recognizes those three kinds of derived types and no others. Thanks for the clarification. [...] >>> A type 'char*' doesn't exist. A type named 'char' does, and assuming >>> that T names an existing type, an object can be declared as 'pointer >>> to a T' by using the syntax >>> >>> T *o; >>> >>> 'Pointerness' is an attribute of the object, not of the type. This is >>> also consistent with the original intention behind this syntax, namely >>> that 'declaration should resemble use'. >> >> Wrong. char* is a type. Specifically, it's a derived type and a >> pointer type. See C99 6.2.5, particularly paragraph 20. > > T *o; > > is a pointer declarator and it means that the type of o is 'pointer to > T', not 'T*' (6.7.5.1|1). So you agree that "pointer to char" is a type, right? The type "pointer to char" is commonly referred, using C syntax, as "char*". I see no problem with referring to it that way. And if the point you were trying to make was the type often referred to as "char*" is properly referred to as "pointer to char", that wasn't at all clear to me from what you wrote. > [...] > >> (And for the record, I agree that "T *o;" is preferable to >> "T* o;"; I just don't agree that it's a huge deal.) > > It's a pointless inconsistency. I don't agree that it's entirely pointless, but I'm not going to argue the point. -- Keith Thompson (The_Other_Keith) kst-u(a)mib.org <http://www.ghoti.net/~kst> Nokia "We must do something. This is something. Therefore, we must do this." -- Antony Jay and Jonathan Lynn, "Yes Minister" |