Re: [PATCH] static const field reassigned in pop3.c



On Mon, 2005-02-21 at 04:21 +0000, Peter Bloomfield wrote:
> I have the hardest time keeping that straight--yes, the latter:  
> const char *service is a pointer to a string that must not be  
> changed; the compiler won't allow assignment to *service (or  
> service[n]).  But assignment to service is fine.
> 
> But if you use
> 
> typedef char *char_p;
> 
> then const char_p service declares a variable that you can't  
> assign to!  That is, you can initialize it, but never change it.   
> There's some binding here that's hard to figure out...  I don't  
> know how you'd declare such a service without the typedef.

FYI: char *const service;

Here is is rule I came up with when I used to teach C++.

Put our finger on the name of the thing being declared (or "typedef"ed)
and then say "<name> is a" followed by the following phrases:
  For *       "pointer to"
  for &       "reference to"
  for conts   "constant(s)"
  for char    "character(s)" (ditto int-> "integers" etc)
  for []      "an array of"
  for (...)   "a function that takes a" then read the contents of
              the ()s followed by "and that returns a"

You must always go right as far as you can before going left but you
must aways finish off bracketed types before leaving the brackets.  So,
for example:

        const char *x;
        "x is a pointer to character constants"

        const char *const x;
        "x is a constant pointer to character constants"

        int (*f)(char);
        "f is a pointer to a function that takes a character an
        that returns an integer" as opposed to:

        int *f(char)
        "f is a function that takes a character and that returns
        a pointer to an integer"

        const char *(*fp[])(void (*g)());
        "fp is an array of pointers to functions [that take a pointer
        to a function that nothing and that returns void] and that
        returns a pointer to character constants"
        
You get very stilted words so it is better to tidy them up in your head
as you read but you get the right meaning at least.  It's helped me a
thousand times and makes it clear when extra parentheses are needed
simply because reading the type comes out wrong without them (as in the
examples declaring f above).

It also works for pure types -- the types themselves.  These are written
as declarations with the name missing so it can be hard to get started.
You have to find where the name *would* be.  E.g. the type of the first
f is "int (*)(char)" and here it is obvious where the name is missing
from, but fp has the truly ghastly type: "const char *(*)(void (*)())"
where it is harder to spot the missing name.

-- 
Ben.




[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]