Difference between following statements

Discussion in 'C Programming' started by deepak, Feb 25, 2013.

  1. deepak

    deepak Guest

    Hi,

    Can someone please clarify difference between following two declaration?

    const char *p;
    char* const p;

    Thanks,
    Deepak
    deepak, Feb 25, 2013
    #1
    1. Advertising

  2. Ben Bacarisse, Feb 25, 2013
    #2
    1. Advertising

  3. deepak

    Paul N Guest

    On Feb 25, 5:24 pm, deepak <> wrote:
    > Hi,
    >
    > Can someone please clarify difference between following two declaration?
    >
    >   const char *p;


    This means p can change, but you can't use it to change the character
    pointed at. For example:

    p = r; // works if r is a suitable pointer
    x = *p; // works if x is a suitable variable
    *p = x; // won't work

    >   char* const p;


    This means you can't change p, but you can use it to change the
    character pointed at. For example:

    p = r; // doesn't work
    x = *p; // works if x is a suitable variable
    *p = x; // also works if x is a suitable variable

    I was going to point you to the C FAQ at http://c-faq.com/ but it
    doesn't seem to answer this question. It's still worth a read though.

    Hope that helps.
    Paul.
    Paul N, Feb 25, 2013
    #3
  4. Paul N <> writes:

    > On Feb 25, 5:24 pm, deepak <> wrote:

    <snip>
    >> Can someone please clarify difference between following two declaration?
    >>
    >>   const char *p;

    <snip>
    >>   char* const p;

    <snip>
    > I was going to point you to the C FAQ at http://c-faq.com/ but it
    > doesn't seem to answer this question.


    It's brief, but it answers it. What do you think is missing? (I'm
    talking of http://c-faq.com/ansi/constptrconst.html i.e. section 11.9.)

    --
    Ben.
    Ben Bacarisse, Feb 25, 2013
    #4
  5. deepak <> writes:
    > Can someone please clarify difference between following two declaration?
    >
    > const char *p;


    declare p as pointer to const char

    > char* const p;


    declare p as const pointer to char

    Source: http://cdecl.org/

    Or you can install and use the "cdecl" command-line tool:

    $ cdecl
    Type `help' or `?' for help
    cdecl> explain const char *p;
    declare p as pointer to const char
    cdecl> explain char* const p;
    declare p as const pointer to char
    cdecl>

    --
    Keith Thompson (The_Other_Keith) <http://www.ghoti.net/~kst>
    Working, but not speaking, for JetHead Development, Inc.
    "We must do something. This is something. Therefore, we must do this."
    -- Antony Jay and Jonathan Lynn, "Yes Minister"
    Keith Thompson, Feb 25, 2013
    #5
  6. deepak

    James Kuyper Guest

    On 02/25/2013 12:39 PM, Paul N wrote:
    > On Feb 25, 5:24�pm, deepak <> wrote:
    >> Hi,
    >>
    >> Can someone please clarify difference between following two declaration?
    >>
    >> � const char *p;

    >
    > This means p can change, but you can't use it to change the character
    > pointed at. For example:
    >
    > p = r; // works if r is a suitable pointer
    > x = *p; // works if x is a suitable variable
    > *p = x; // won't work
    >
    >> � char* const p;

    >
    > This means you can't change p, but you can use it to change the
    > character pointed at. For example:
    >
    > p = r; // doesn't work
    > x = *p; // works if x is a suitable variable
    > *p = x; // also works if x is a suitable variable
    >
    > I was going to point you to the C FAQ at http://c-faq.com/ but it
    > doesn't seem to answer this question. It's still worth a read though.


    It's not quite correct to say that you can't do those things, and the
    section of the FAQ that Ben referred doesn't go into the relevant issues
    either. It would be more accurate to say that any attempt to do those
    things is a constraint violation, which requires a diagnostic message.
    Making that message mandatory is the main purpose for using 'const' in a
    declaration. If you know that a given pointer should not be used to try
    to change something, you can insert 'const' in the appropriate part of
    the declaration to get the compiler to warn you if your code actually
    does attempt to misuse it in that fashion. Either the attempt to change
    the corresponding object was a mistake, or the belief that the variable
    should not be used to make such changes was a mistake - you'll have to
    investigate to determine which one was wrong. But at least, with the
    message, you'll know there was a conflict.

    However, after having issued a diagnostic, a compiler is still free to
    translate your code into a program. If you choose to execute that
    program, it's behavior is undefined. That means, among other
    possibilities, that the program might in fact change something it should
    not have changed (even objects defined as 'const').

    You can disable the diagnostic message by casting the pointer to an
    appropriate non-const type. Never do this unless you're sure it's both
    necessary and correct - consider whether it would be more appropriate to
    remove the 'const' from the declaration, rather than casting it away.

    It might be perfectly safe to write code that bypasses those warnings
    using a cast. However, one thing a cast cannot do for you is allow you
    to safely change the contents of an object which is itself defined as
    'const' (rather than, for instance, a pointer to 'const'). The behavior
    is always undefined if your code attempts that,
    --
    James Kuyper
    James Kuyper, Feb 25, 2013
    #6
  7. deepak

    Shao Miller Guest

    On 2/25/2013 12:24, deepak wrote:
    > Can someone please clarify difference between following two declaration?
    >
    > const char *p;
    > char* const p;
    >


    int main(void) {
    const char (* (p));
    char (* const (q));

    const char (* const (r));
    char const (* const (s));

    return 0;
    }

    In the first, the reference type is 'const char' and 'p' is an
    unqualified pointer to that type. You can assign to 'p'.

    In the second, the reference type is 'char' and 'q' is a const-qualified
    pointer to that type. You cannot assign to 'q'. Because there's no
    initializer, 'q' in the example code is worse than useless.

    In the third and fourth, the reference types are the same: 'const char'.
    'r' and 's' are const-qualified pointers to that type. You cannot
    assign to either of them, and without initializers, they are both worse
    than useless.

    --
    - Shao Miller
    --
    "Thank you for the kind words; those are the kind of words I like to hear.

    Cheerily," -- Richard Harter
    Shao Miller, Feb 25, 2013
    #7
  8. In article <>,
    deepak <> wrote:
    >Hi,
    >
    >Can someone please clarify difference between following two declaration?
    >
    > const char *p;
    > char* const p;


    In general, the 'const' applies to whatever immediately follows.

    From my notes:

    const int x = 44; x cannot change
    const int *z; *z cannot change
    int * const z; z cannot change
    const int *const z; z cannot change and *z cannot change

    char **s; pointer to pointer to char
    const char * * s pointer to pointer to const char
    char const * * s pointer to pointer to const char
    char * const * s pointer to const pointer to char
    char * * const s const pointer to pointer to char
    char * const * const s const ptr to const ptr to char

    const struct employee {
    char *name;
    int birthdate;
    int job_code;
    } a,b; no member or a or b can change

    struct employee c,d; but c and d are not const

    struct employee {
    char *name;
    const int birthdate; this member cannot change
    int job_code;
    };


    --
    -Ed Falk,
    http://thespamdiaries.blogspot.com/
    Edward A. Falk, Feb 25, 2013
    #8
  9. (Edward A. Falk) writes:

    >> const char *p;
    >> char* const p;

    >
    > In general, the 'const' applies to whatever immediately follows.


    s/follows/precedes/

    (placing it at the extreme left is a convenience, and the only case
    where it applies to what follows).

    [...]
    > const char * * s pointer to pointer to const char
    > char const * * s pointer to pointer to const char


    We agree, const applies to the char.

    > char * const * s pointer to const pointer to char
    > char * * const s const pointer to pointer to char
    > char * const * const s const ptr to const ptr to char


    and, for completeness, the twins:

    const char * const * const s
    char const * const * const s

    where everything is const.

    -- Alain.
    Alain Ketterlin, Feb 25, 2013
    #9
  10. Shao Miller <> writes:
    > On 2/25/2013 12:24, deepak wrote:
    >> Can someone please clarify difference between following two declaration?
    >>
    >> const char *p;
    >> char* const p;
    >>

    >
    > int main(void) {
    > const char (* (p));
    > char (* const (q));
    >
    > const char (* const (r));
    > char const (* const (s));
    >
    > return 0;
    > }
    >
    > In the first, the reference type is 'const char' and 'p' is an
    > unqualified pointer to that type. You can assign to 'p'.
    >
    > In the second, the reference type is 'char' and 'q' is a const-qualified
    > pointer to that type. You cannot assign to 'q'. Because there's no
    > initializer, 'q' in the example code is worse than useless.
    >
    > In the third and fourth, the reference types are the same: 'const char'.
    > 'r' and 's' are const-qualified pointers to that type. You cannot
    > assign to either of them, and without initializers, they are both worse
    > than useless.


    In all cases, I think you mean "referenced type" rather than
    "reference type".

    For a "pointer to FOO" type, "FOO" is the "referenced type".
    The term is introduced in N1570 6.2.5p20.

    (The phrase "reference type" could be confused with the C++ feature
    of that name, something that doesn't exist in C.)

    --
    Keith Thompson (The_Other_Keith) <http://www.ghoti.net/~kst>
    Working, but not speaking, for JetHead Development, Inc.
    "We must do something. This is something. Therefore, we must do this."
    -- Antony Jay and Jonathan Lynn, "Yes Minister"
    Keith Thompson, Feb 25, 2013
    #10
  11. deepak

    Shao Miller Guest

    On 2/25/2013 16:46, Keith Thompson wrote:
    > Shao Miller <> writes:
    >> On 2/25/2013 12:24, deepak wrote:
    >>> Can someone please clarify difference between following two declaration?
    >>>
    >>> const char *p;
    >>> char* const p;
    >>>

    >>
    >> int main(void) {
    >> const char (* (p));
    >> char (* const (q));
    >>
    >> const char (* const (r));
    >> char const (* const (s));
    >>
    >> return 0;
    >> }
    >>
    >> In the first, the reference type is 'const char' and 'p' is an
    >> unqualified pointer to that type. You can assign to 'p'.
    >>
    >> In the second, the reference type is 'char' and 'q' is a const-qualified
    >> pointer to that type. You cannot assign to 'q'. Because there's no
    >> initializer, 'q' in the example code is worse than useless.
    >>
    >> In the third and fourth, the reference types are the same: 'const char'.
    >> 'r' and 's' are const-qualified pointers to that type. You cannot
    >> assign to either of them, and without initializers, they are both worse
    >> than useless.

    >
    > In all cases, I think you mean "referenced type" rather than
    > "reference type".
    >
    > For a "pointer to FOO" type, "FOO" is the "referenced type".
    > The term is introduced in N1570 6.2.5p20.
    >
    > (The phrase "reference type" could be confused with the C++ feature
    > of that name, something that doesn't exist in C.)
    >


    Quite right; thanks! As a nit-pick, I believe that "referenced type"
    was in C89/C90, then wasn't in C99, and now has returned for C11.

    --
    - Shao Miller
    --
    "Thank you for the kind words; those are the kind of words I like to hear.

    Cheerily," -- Richard Harter
    Shao Miller, Feb 25, 2013
    #11
  12. deepak

    James Kuyper Guest

    On 02/25/2013 03:05 PM, Alain Ketterlin wrote:
    > (Edward A. Falk) writes:
    >
    >>> const char *p;
    >>> char* const p;

    >>
    >> In general, the 'const' applies to whatever immediately follows.

    >
    > s/follows/precedes/
    >
    > (placing it at the extreme left is a convenience, and the only case
    > where it applies to what follows).
    >
    > [...]
    >> const char * * s pointer to pointer to const char
    >> char const * * s pointer to pointer to const char

    >
    > We agree, const applies to the char.


    In both cases **s is what cannot change, and **s follows the keyword const.

    >> char * const * s pointer to const pointer to char


    In this case, *s is what cannot change, and *s follows the keyword const.

    >> char * * const s const pointer to pointer to char


    In this case, s cannot change, because it is what follows the keyword
    'const'.

    >> char * const * const s const ptr to const ptr to char


    In this case, *s cannot change, because that's what follows the first
    'const', and s itself also cannot change, because that's what follows
    the second 'const'.

    If you believe that the word "follows" should be replaced by "precedes",
    I presume that either you disagree with my descriptions, or you apply
    the rule in a different manner. Could you explain?
    --
    James Kuyper
    James Kuyper, Feb 25, 2013
    #12
  13. deepak

    Shao Miller Guest

    On 2/25/2013 17:20, James Kuyper wrote:
    > On 02/25/2013 03:05 PM, Alain Ketterlin wrote:
    >> (Edward A. Falk) writes:
    >>
    >>>> const char *p;
    >>>> char* const p;
    >>>
    >>> In general, the 'const' applies to whatever immediately follows.

    >>
    >> s/follows/precedes/
    >>
    >> (placing it at the extreme left is a convenience, and the only case
    >> where it applies to what follows).
    >>
    >> [...]
    >>> const char * * s pointer to pointer to const char
    >>> char const * * s pointer to pointer to const char

    >>
    >> We agree, const applies to the char.

    >
    > In both cases **s is what cannot change, and **s follows the keyword const.
    >
    >>> char * const * s pointer to const pointer to char

    >
    > In this case, *s is what cannot change, and *s follows the keyword const.
    >
    >>> char * * const s const pointer to pointer to char

    >
    > In this case, s cannot change, because it is what follows the keyword
    > 'const'.
    >
    >>> char * const * const s const ptr to const ptr to char

    >
    > In this case, *s cannot change, because that's what follows the first
    > 'const', and s itself also cannot change, because that's what follows
    > the second 'const'.
    >
    > If you believe that the word "follows" should be replaced by "precedes",
    > I presume that either you disagree with my descriptions, or you apply
    > the rule in a different manner. Could you explain?
    >


    Reading the type as English can sometimes involve working backwards.
    For the last example, 's' is a "constant pointer to a constant pointer
    to a character," which is the opposite order to the syntactical elements
    as they appear. This could explain the discrepancy.

    --
    - Shao Miller
    --
    "Thank you for the kind words; those are the kind of words I like to hear.

    Cheerily," -- Richard Harter
    Shao Miller, Feb 25, 2013
    #13
  14. Shao Miller <> writes:

    > On 2/25/2013 17:20, James Kuyper wrote:
    >> On 02/25/2013 03:05 PM, Alain Ketterlin wrote:
    >>> (Edward A. Falk) writes:


    [...]
    >>>> In general, the 'const' applies to whatever immediately follows.
    >>>
    >>> s/follows/precedes/

    [...]
    >>>> char * const * s pointer to const pointer to char

    >>
    >> In this case, *s is what cannot change, and *s follows the keyword const.

    [...]

    Yes but we're talking about types, and const qualifies the type that
    precedes, which is "char *". How would you call "*s" in your example?
    Let's call this a "potential expression". Then, const applies to the
    type that precedes and to the potential expression that follows
    (ignoring other const qualifiers appearing, e.g., char const * const s).

    >> If you believe that the word "follows" should be replaced by "precedes",
    >> I presume that either you disagree with my descriptions, or you apply
    >> the rule in a different manner. Could you explain?

    >
    > Reading the type as English can sometimes involve working backwards.
    > For the last example, 's' is a "constant pointer to a constant pointer
    > to a character," which is the opposite order to the syntactical
    > elements as they appear. This could explain the discrepancy.


    Exactly. The C++ faq suggest reading right-to-left to understand pointer
    declarations with const.

    -- Alain.
    Alain Ketterlin, Feb 25, 2013
    #14
  15. Shao Miller <> writes:
    > On 2/25/2013 16:46, Keith Thompson wrote:

    [...]
    >> In all cases, I think you mean "referenced type" rather than
    >> "reference type".
    >>
    >> For a "pointer to FOO" type, "FOO" is the "referenced type".
    >> The term is introduced in N1570 6.2.5p20.
    >>
    >> (The phrase "reference type" could be confused with the C++ feature
    >> of that name, something that doesn't exist in C.)

    >
    > Quite right; thanks! As a nit-pick, I believe that "referenced type"
    > was in C89/C90, then wasn't in C99, and now has returned for C11.


    It's in C90, C99, N1256, and N1570. (I presume it's in the released
    2011 standard; my copy isn't handy.)

    --
    Keith Thompson (The_Other_Keith) <http://www.ghoti.net/~kst>
    Working, but not speaking, for JetHead Development, Inc.
    "We must do something. This is something. Therefore, we must do this."
    -- Antony Jay and Jonathan Lynn, "Yes Minister"
    Keith Thompson, Feb 25, 2013
    #15
  16. deepak

    James Kuyper Guest

    On 02/25/2013 06:11 PM, Alain Ketterlin wrote:
    > Shao Miller <> writes:
    >
    >> On 2/25/2013 17:20, James Kuyper wrote:
    >>> On 02/25/2013 03:05 PM, Alain Ketterlin wrote:
    >>>> (Edward A. Falk) writes:

    >
    > [...]
    >>>>> In general, the 'const' applies to whatever immediately follows.
    >>>>
    >>>> s/follows/precedes/

    > [...]
    >>>>> char * const * s pointer to const pointer to char
    >>>
    >>> In this case, *s is what cannot change, and *s follows the keyword const.

    > [...]
    >
    > Yes but we're talking about types, ...


    No, I'm talking about expressions. Since you were talking about types,
    that would explain the discrepancy. You may find it easier to think
    about 'const' in terms of the type it modifies. I find it easier to
    think about it in terms of the expressions that it turns into constraint
    violations.

    > ... and const qualifies the type that
    > precedes, which is "char *". How would you call "*s" in your example?


    I'd call it an lvalue expression, potentially referring to an object,
    and it is precisely such an expression whose presence as the left
    operand of an assignment or compound assignment expression, or as the
    only operand of an increment or decrement expression, that would violate
    a constraint because of the preceding 'const' keyword.
    --
    James Kuyper
    James Kuyper, Feb 26, 2013
    #16
  17. deepak

    John Bode Guest

    On Monday, February 25, 2013 11:24:09 AM UTC-6, deepak wrote:
    > Hi,
    >
    > Can someone please clarify difference between following two declaration?
    >
    > const char *p;
    > char* const p;
    >
    > Thanks,
    > Deepak


    In the first case, p is a pointer to a const char; you can modify p
    (set it to point to a different thing), but you cannot modify
    what p points to.

    In the second case, p is a const pointer to a non-const char; you
    can modify what p points to, but you cannot modify p (cannot set
    it to point to a different thing).

    Since attempting to modify a string literal invokes undefined behavior,
    many people recommend declaring a pointer to it as const char *, such
    as

    const char *str = "string literal";

    If you try to modify the contents of the literal through str, the compiler
    will complain.
    John Bode, Feb 26, 2013
    #17
  18. deepak

    Paul N Guest

    On Feb 25, 5:54 pm, Ben Bacarisse <> wrote:
    > Paul N <> writes:
    > > On Feb 25, 5:24 pm, deepak <> wrote:

    > <snip>
    > >> Can someone please clarify difference between following two declaration?

    >
    > >>   const char *p;

    > <snip>
    > >>   char* const p;

    > <snip>
    > > I was going to point you to the C FAQ athttp://c-faq.com/but it
    > > doesn't seem to answer this question.

    >
    > It's brief, but it answers it.  What do you think is missing?  (I'm
    > talking of http://c-faq.com/ansi/constptrconst.html i.e. section 11.9.)


    Ah, I thought it was in the FAQ somewhere, but at a quick look I
    couldn't find it. As the question is about pointer declarations, one
    might expect it to be either in Section 1 - Declarations and
    Initializations - or Section 4 - Pointers - but it doesn't seem to
    appear in either of these, even as a reference to an answer elsewhere.
    Paul N, Feb 26, 2013
    #18
  19. deepak

    James Kuyper Guest

    On 02/26/2013 05:49 PM, Paul N wrote:
    > On Feb 25, 5:54 pm, Ben Bacarisse <> wrote:
    >> Paul N <> writes:
    >>> On Feb 25, 5:24 pm, deepak <> wrote:

    >> <snip>
    >>>> Can someone please clarify difference between following two declaration?

    >>
    >>>> const char *p;

    >> <snip>
    >>>> char* const p;

    >> <snip>
    >>> I was going to point you to the C FAQ athttp://c-faq.com/but it
    >>> doesn't seem to answer this question.

    >>
    >> It's brief, but it answers it. What do you think is missing? (I'm
    >> talking of http://c-faq.com/ansi/constptrconst.html i.e. section 11.9.)

    >
    > Ah, I thought it was in the FAQ somewhere, but at a quick look I
    > couldn't find it. As the question is about pointer declarations, one
    > might expect it to be either in Section 1 - Declarations and
    > Initializations ...


    It is - see question 1.20 (the answer cross references 11.9)
    James Kuyper, Feb 26, 2013
    #19
  20. deepak

    army1987 Guest

    On Mon, 25 Feb 2013 09:24:09 -0800, deepak wrote:

    > Can someone please clarify difference between following two declaration?


    <nitpick>Contrary to what you seem to imply in the subject line,
    declarations are not statements. (This means that, as IIRC was mentioned
    somewhere recently, `if (something) int i;` is a syntax error.)</nitpick>




    --
    [ T H I S S P A C E I S F O R R E N T ]
    Troppo poca cultura ci rende ignoranti, troppa ci rende folli.
    -- fathermckenzie di it.cultura.linguistica.italiano
    <http://xkcd.com/397/>
    army1987, Mar 1, 2013
    #20
    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. Neil Zanella
    Replies:
    8
    Views:
    1,181
    mfmehdi
    Oct 20, 2006
  2. jakk
    Replies:
    4
    Views:
    12,115
  3. ATSkyWalker
    Replies:
    11
    Views:
    562
    tiissa
    Apr 20, 2005
  4. RN1
    Replies:
    3
    Views:
    271
    Juan T. Llibre
    Apr 14, 2008
  5. Doney Kaka
    Replies:
    9
    Views:
    136
    Josh Cheek
    Nov 19, 2009
Loading...

Share This Page