help with 'left-right' cdecl rule

Discussion in 'C Programming' started by James Brown [MVP], Feb 13, 2006.

  1. Hi,
    I am having trouble understanding how the 'const' modifier affects the
    'left-right' rule when deciphering c-declarations:

    const int *x; // x is a pointer to a 'const int'
    int const *x; // ??

    these are the same, right? in this case the basetype is 'const int' ?

    int * const x = 0; // x is a const-pointer to int
    int (* const )x = 0; // same as above

    do the brackets have any significance here? I think not in this case..

    int (const * x)[2]; // x is a const-pointer to array[2] of int
    int const *x[2]; // x is an array[2] of const-pointer to int

    have I understood these correctly?

    really I am having trouble understanding what the significance is of the
    const-keyword being on the left or right of a '*'...I am writing a small
    c-declaration parser as this is helping me to understand the syntax of
    c-style declarations..

    thanks,
    James
     
    James Brown [MVP], Feb 13, 2006
    #1
    1. Advertising

  2. James Brown [MVP]

    Guest

    James Brown [MVP] wrote:
    > Hi,
    > I am having trouble understanding how the 'const' modifier affects the
    > 'left-right' rule when deciphering c-declarations:
    >
    > const int *x; // x is a pointer to a 'const int'
    > int const *x; // ??


    I think the first declaration would be:
    x is pointer to a const int meaning you have a modifiable pointer but
    what it points to is not.

    The second is
    x is const pointer to int which means you have an unmodifiable pointer,
    but what it points to is modifiable.

    > these are the same, right? in this case the basetype is 'const int' ?


    I think the basetype is just int. One declaration is making a const
    pointer to an int, and one is making a pointer to a const int.

    I'm nowhere near an expert in C, but this is my take.

    > int * const x = 0; // x is a const-pointer to int
    > int (* const )x = 0; // same as above
    >
    > do the brackets have any significance here? I think not in this case..
    >
    > int (const * x)[2]; // x is a const-pointer to array[2] of int
    > int const *x[2]; // x is an array[2] of const-pointer to int
    >
    > have I understood these correctly?
    >
    > really I am having trouble understanding what the significance is of the
    > const-keyword being on the left or right of a '*'...I am writing a small
    > c-declaration parser as this is helping me to understand the syntax of
    > c-style declarations..
    >
    > thanks,
    > James
     
    , Feb 13, 2006
    #2
    1. Advertising

  3. James Brown [MVP]

    Michael Mair Guest

    wrote:
    > James Brown [MVP] wrote:
    >
    >>Hi,
    >>I am having trouble understanding how the 'const' modifier affects the
    >>'left-right' rule when deciphering c-declarations:
    >>
    >>const int *x; // x is a pointer to a 'const int'
    >>int const *x; // ??

    >
    > I think the first declaration would be:
    > x is pointer to a const int meaning you have a modifiable pointer but
    > what it points to is not.
    >
    > The second is
    > x is const pointer to int which means you have an unmodifiable pointer,
    > but what it points to is modifiable.


    Nope. It is a pointer to a const int.

    >>these are the same, right? in this case the basetype is 'const int' ?


    Yes. The position of const (or volatile) with respect to the
    type is not fixed and there have been long and hot discussions
    about which version is "better".

    > I think the basetype is just int. One declaration is making a const
    > pointer to an int, and one is making a pointer to a const int.
    >
    > I'm nowhere near an expert in C, but this is my take.


    Nope. "int * const" is what you describe.

    >>int * const x = 0; // x is a const-pointer to int
    >>int (* const )x = 0; // same as above
    >>
    >>do the brackets have any significance here? I think not in this case..
    >>
    >>int (const * x)[2]; // x is a const-pointer to array[2] of int
    >>int const *x[2]; // x is an array[2] of const-pointer to int
    >>
    >>have I understood these correctly?
    >>
    >>really I am having trouble understanding what the significance is of the
    >>const-keyword being on the left or right of a '*'...I am writing a small
    >>c-declaration parser as this is helping me to understand the syntax of
    >>c-style declarations..


    Get yourself cdecl to test against; AFAIR there was a thread in
    clc not too long ago where people discussed their homebrew cdecl
    variants and the "original".

    BTW: If you are motivated, try to cover C99 declarations as well
    (-> restrict, -> static in function parameter array declarations)


    Cheers
    Michael
    --
    E-Mail: Mine is an /at/ gmx /dot/ de address.
     
    Michael Mair, Feb 13, 2006
    #3
  4. James Brown [MVP]

    Guest

    Michael Mair wrote:
    > wrote:
    > > James Brown [MVP] wrote:
    > >
    > >>Hi,
    > >>I am having trouble understanding how the 'const' modifier affects the
    > >>'left-right' rule when deciphering c-declarations:
    > >>
    > >>const int *x; // x is a pointer to a 'const int'
    > >>int const *x; // ??

    > >
    > > I think the first declaration would be:
    > > x is pointer to a const int meaning you have a modifiable pointer but
    > > what it points to is not.
    > >
    > > The second is
    > > x is const pointer to int which means you have an unmodifiable pointer,
    > > but what it points to is modifiable.

    >
    > Nope. It is a pointer to a const int.


    Right you are. I looked and found this explicit answer:
    http://c-faq.com/ansi/constptrconst.html

    However, that's just mean. That's why I stay away from C too. Why
    have 3 ways to declare it?

    >
    > >>these are the same, right? in this case the basetype is 'const int' ?

    >
    > Yes. The position of const (or volatile) with respect to the
    > type is not fixed and there have been long and hot discussions
    > about which version is "better".
    >
    > > I think the basetype is just int. One declaration is making a const
    > > pointer to an int, and one is making a pointer to a const int.
    > >
    > > I'm nowhere near an expert in C, but this is my take.

    >
    > Nope. "int * const" is what you describe.


    In the FAQ they said to read from inside out. So yeah, this does make
    sense
    foo is a const pointer to int.

    This "const int * foo" also makes sense, foo is a pointer to a const
    int.

    But, "int const * foo" is just lame. I checked just for clarity's sake
    to see if this is the same in C++ (it is) and the site had this to say.

    "Basically 'const' applies to whatever is on its immediate left
    other than if there is nothing there in which case it applies to
    whatever is its immediate right)." Can we say confusing?



    >
    > >>int * const x = 0; // x is a const-pointer to int
    > >>int (* const )x = 0; // same as above
    > >>
    > >>do the brackets have any significance here? I think not in this case..
    > >>
    > >>int (const * x)[2]; // x is a const-pointer to array[2] of int
    > >>int const *x[2]; // x is an array[2] of const-pointer to int
    > >>
    > >>have I understood these correctly?
    > >>
    > >>really I am having trouble understanding what the significance is of the
    > >>const-keyword being on the left or right of a '*'...I am writing a small
    > >>c-declaration parser as this is helping me to understand the syntax of
    > >>c-style declarations..

    >
    > Get yourself cdecl to test against; AFAIR there was a thread in
    > clc not too long ago where people discussed their homebrew cdecl
    > variants and the "original".
    >
    > BTW: If you are motivated, try to cover C99 declarations as well
    > (-> restrict, -> static in function parameter array declarations)
    >
    >
    > Cheers
    > Michael
    > --
    > E-Mail: Mine is an /at/ gmx /dot/ de address.
     
    , Feb 13, 2006
    #4
  5. James Brown [MVP]

    Old Wolf Guest

    wrote:
    > In the FAQ they said to read from inside out. So yeah, this does make
    > sense foo is a const pointer to int.
    >
    > This "const int * foo" also makes sense, foo is a pointer to a const
    > int.
    >
    > But, "int const * foo" is just lame. I checked just for clarity's sake
    > to see if this is the same in C++ (it is) and the site had this to say.
    >


    It is the "const int * foo" version which is lame.
    Reading from insde out, as you suggest:

    const int * foo foo is a pointer to an int constant
    int const * foo foo is a pointer to a constant int

    > "Basically 'const' applies to whatever is on its immediate left
    > other than if there is nothing there in which case it applies to
    > whatever is its immediate right)." Can we say confusing?


    The "int const * foo" version obeys the first part of this rule,
    the confusing exception is necessary to cover the case of
    "const int * foo" .
     
    Old Wolf, Feb 14, 2006
    #5
  6. James Brown [MVP]

    Robin Haigh Guest

    "James Brown [MVP]" <not@home> wrote in message
    news:...
    > Hi,
    > I am having trouble understanding how the 'const' modifier affects the
    > 'left-right' rule when deciphering c-declarations:
    >
    > const int *x; // x is a pointer to a 'const int'
    > int const *x; // ??
    >
    > these are the same, right? in this case the basetype is 'const int' ?
    >
    > int * const x = 0; // x is a const-pointer to int
    > int (* const )x = 0; // same as above
    >
    > do the brackets have any significance here? I think not in this case..



    The 2nd is a syntax error, as I read it. If there are brackets, the
    variable name (or typedef name) is inside the innermost brackets, except
    when it's omitted altogether. But

    int *const x = 0;
    int (*const x) = 0;

    are the same.


    >
    > int (const * x)[2]; // x is a const-pointer to array[2] of int



    A pointer you can't modify is always *const, not const*. Other types can
    have const before or after.


    > int const *x[2]; // x is an array[2] of const-pointer to int


    so this is array[2] of pointer to const int


    --
    RSH
     
    Robin Haigh, Feb 14, 2006
    #6
  7. On Mon, 13 Feb 2006 17:12:16 -0800, Old Wolf wrote:

    > wrote:
    >> In the FAQ they said to read from inside out. So yeah, this does make
    >> sense foo is a const pointer to int.
    >>
    >> This "const int * foo" also makes sense, foo is a pointer to a const
    >> int.
    >>
    >> But, "int const * foo" is just lame. I checked just for clarity's sake
    >> to see if this is the same in C++ (it is) and the site had this to say.
    >>
    >>

    > It is the "const int * foo" version which is lame. Reading from insde out,
    > as you suggest:
    >
    > const int * foo foo is a pointer to an int constant int const * foo
    > foo is a pointer to a constant int
    >
    >> "Basically 'const' applies to whatever is on its immediate left other
    >> than if there is nothing there in which case it applies to whatever is
    >> its immediate right)." Can we say confusing?

    >
    > The "int const * foo" version obeys the first part of this rule, the
    > confusing exception is necessary to cover the case of "const int * foo" .


    I find it easier not to think in terms of rules with exceptions. C type
    declarations are structred like nested expressions. The various tokens
    int, cont, *, [], () and so on behave like "type operators" applied to the
    thing being declared. As a result, declarations need to be read "inside
    out" starting from the name. You always read to the right first if you
    can (function brakets and array brakets) and then to the left where you
    will find * and const and volatile and so on.

    Because the type may be nested, you may have to finish off an inner
    bracketed part before continuing outside -- again reading to the right if
    there is anything there before going left.

    You can work out an exact list of what to say when you hit a particular
    tokens (<OT>very useful for C++ pointer to member function types that can
    be hard to read at first</OT>) but the main parts are:

    <name> -- say: "name is a"
    ( -- say: "function taking" then read the declarators for the
    formal parameters (say "unknown" if there are none)
    ) -- say: "and returning a"
    [ -- say: "array of"
    ] -- say: nothing
    * -- say: "pointer to a"
    const -- say: "constant"
    int, etc -- say: "int" or "character" or whatever
    <num> -- read out the number

    If you hit a ")" without having read out the opening "(" then you are
    inside a nested type and you have to finish reading it (by going left)
    before jumping out. When you hit the matching "(" you just continue as if
    the barcketed part were no longer there (i.e. start reading to the right
    again).

    As a result, you clear up "int const *x" and "const int *x" for free
    since they read as "x is a pointer to a constant int" and "x is a pointer
    to an int constant" which have the same natural meaning in English.

    It really pays off with pointer to function types:

    int const *const (*f)(void);

    Goes: "f is a" -- can't go right because of the ")" so we are in a nested
    type and need to finish it -- "pointer to a" -- we can now remove the
    nested part and keep going -- "function taking void and
    returning a constant pointer to constant int".

    It is simpler to do that is sounds, honest! (The hardest part is spotting
    where the name should be when you are reading the type in a cast or a
    nameless formal paramater -- these look just like a declarations but with
    the name missing).

    --
    Ben.
     
    Ben Bacarisse, Feb 14, 2006
    #7
    1. Advertising

Want to reply to this thread or ask your own question?

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. =?Utf-8?B?QmlzaG95?=
    Replies:
    0
    Views:
    1,051
    =?Utf-8?B?QmlzaG95?=
    Dec 28, 2006
  2. Replies:
    0
    Views:
    1,415
  3. Tor Rustad

    cdecl test cases

    Tor Rustad, Mar 21, 2005, in forum: C Programming
    Replies:
    12
    Views:
    764
    Kevin D. Quitt
    Mar 28, 2005
  4. Replies:
    5
    Views:
    430
  5. Oran
    Replies:
    2
    Views:
    604
Loading...

Share This Page