const char* vs char const*

Discussion in 'C++' started by engineer, May 28, 2013.

  1. engineer

    engineer Guest

    Hi,

    Can someone give me an easy explanation as well as the difference between the following three statements.

    const char* p
    char const* m
    char* const n

    thanks
    -Ahmed
     
    engineer, May 28, 2013
    #1
    1. Advertising

  2. engineer

    Öö Tiib Guest

    On Tuesday, 28 May 2013 12:30:39 UTC+3, engineer wrote:
    > Can someone give me an easy explanation as well as the difference between
    > the following three statements.
    >
    > const char* p
    > char const* m
    > char* const n


    There are no difference between type of 'p' and 'm'. Both are mutable
    pointers to immutable char. 'n' is immutable pointer to mutable char.
     
    Öö Tiib, May 28, 2013
    #2
    1. Advertising

  3. Öö Tiib wrote:

    > On Tuesday, 28 May 2013 12:30:39 UTC+3, engineer wrote:
    >> Can someone give me an easy explanation as well as the difference between
    >> the following three statements.
    >>
    >> const char* p
    >> char const* m
    >> char* const n

    >
    > There are no difference between type of 'p' and 'm'. Both are mutable
    > pointers to immutable char. 'n' is immutable pointer to mutable char.


    In addition to what Öö wrote: Try to read the type declaration from
    right to left, "translating" * with "pointer to", "const" with
    "immutable" and considering that an "immutable char" is the same (in
    this context) as a "char immutable".

    Gerhard
     
    Gerhard Fiedler, May 28, 2013
    #3
  4. engineer

    James Kanze Guest

    On Tuesday, May 28, 2013 10:30:39 AM UTC+1, engineer wrote:
    > Can someone give me an easy explanation as well as the
    > difference between the following three statements.


    > const char* p
    > char const* m
    > char* const n


    Just apply the general rule: const applies to whatever is
    immediately to the left of it. If nothing is to the immediate
    left of it, move it to the right until there is something.
    Thus:

    const char* p; // The same as char const* p (which would be preferable)
    char const* m; // (non-const) pointer to const char.
    char *const n; // Const pointer to (non-const) char.
    char const* const* o; // Const pointer to const char.

    In an ideal world, you'd never see the first declaration you
    give, as it leads to a great deal of confusion when typedefs are
    involved:

    typedef char* CPtr;
    CPtr const p1; // char *const p1
    const CPtr p2; // char *const p2 !!!

    --
    James
     
    James Kanze, May 29, 2013
    #4
  5. engineer

    Jorgen Grahn Guest

    On Wed, 2013-05-29, James Kanze wrote:
    > On Tuesday, May 28, 2013 10:30:39 AM UTC+1, engineer wrote:
    >> Can someone give me an easy explanation as well as the
    >> difference between the following three statements.

    >
    >> const char* p
    >> char const* m
    >> char* const n

    >
    > Just apply the general rule: const applies to whatever is
    > immediately to the left of it. If nothing is to the immediate
    > left of it, move it to the right until there is something.
    > Thus:
    >
    > const char* p; // The same as char const* p (which would be preferable)
    > char const* m; // (non-const) pointer to const char.
    > char *const n; // Const pointer to (non-const) char.
    > char const* const* o; // Const pointer to const char.
    >
    > In an ideal world, you'd never see the first declaration you
    > give, as it leads to a great deal of confusion when typedefs are
    > involved:
    >
    > typedef char* CPtr;
    > CPtr const p1; // char *const p1
    > const CPtr p2; // char *const p2 !!!


    I think you're wrong here -- the const cannot "invade" the typedef, so
    both p1 and p2 are constant pointers to non-const stuff, like you'd
    expect.

    Of course, many would say that in ideal world you don't see a lot of
    typedef:ed pointers either. They are a source of confusion too.

    /Jorgen

    --
    // Jorgen Grahn <grahn@ Oo o. . .
    \X/ snipabacken.se> O o .
     
    Jorgen Grahn, May 31, 2013
    #5
  6. engineer

    Öö Tiib Guest

    On Friday, 31 May 2013 11:33:18 UTC+3, Jorgen Grahn wrote:
    > Of course, many would say that in ideal world you don't see a lot of
    > typedef:ed pointers either. They are a source of confusion too.


    Can you describe the situation where those many would say that?

    For example: All C++ standard library containers (and some non-containers)
    have 'pointer' and 'const_pointer' member typedefs. Some non-containers
    have such typedefs as well. Some people ignore these, some use.
    Lack of such typedefs (in a weakly made custom container) may cause
    inconvenience for people who expect such typedefs ... but what confusion?
     
    Öö Tiib, May 31, 2013
    #6
  7. engineer

    James Kanze Guest

    On Friday, May 31, 2013 9:33:18 AM UTC+1, Jorgen Grahn wrote:
    > On Wed, 2013-05-29, James Kanze wrote:
    > > On Tuesday, May 28, 2013 10:30:39 AM UTC+1, engineer wrote:
    > >> Can someone give me an easy explanation as well as the
    > >> difference between the following three statements.


    > >> const char* p
    > >> char const* m
    > >> char* const n


    > > Just apply the general rule: const applies to whatever is
    > > immediately to the left of it. If nothing is to the immediate
    > > left of it, move it to the right until there is something.
    > > Thus:


    > > const char* p; // The same as char const* p (which would be preferable)
    > > char const* m; // (non-const) pointer to const char.
    > > char *const n; // Const pointer to (non-const) char.
    > > char const* const* o; // Const pointer to const char.


    > > In an ideal world, you'd never see the first declaration you
    > > give, as it leads to a great deal of confusion when typedefs are
    > > involved:


    > > typedef char* CPtr;
    > > CPtr const p1; // char *const p1
    > > const CPtr p2; // char *const p2 !!!


    > I think you're wrong here -- the const cannot "invade" the typedef, so
    > both p1 and p2 are constant pointers to non-const stuff, like you'd
    > expect.


    That's what I said, no?

    > Of course, many would say that in ideal world you don't see a lot of
    > typedef:ed pointers either. They are a source of confusion too.


    I'm tempted to say "wishful thinking". I agree that typedef'ing
    pointers is bad policy. But the same problems occur in more
    complicated cases, where people are typedef'ing pointers to
    member functions, or whatever. (Of course, I would argue that
    even then, typedef's cause confusion. But given the syntax,
    people do want to do it.)

    --
    James
     
    James Kanze, May 31, 2013
    #7
  8. engineer

    James Kanze Guest

    On Friday, May 31, 2013 10:05:28 AM UTC+1, Öö Tiib wrote:
    > On Friday, 31 May 2013 11:33:18 UTC+3, Jorgen Grahn wrote:
    > > Of course, many would say that in ideal world you don't see a lot of
    > > typedef:ed pointers either. They are a source of confusion too.


    > Can you describe the situation where those many would say that?


    > For example: All C++ standard library containers (and some non-containers)
    > have 'pointer' and 'const_pointer' member typedefs. Some non-containers
    > have such typedefs as well. Some people ignore these, some use.
    > Lack of such typedefs (in a weakly made custom container) may cause
    > inconvenience for people who expect such typedefs ... but what confusion?


    The situation is a bit different there. 'pointer' and
    'const_pointer' are *not* necessarily T* and T const*. And the
    typedef's are really only for use in template functions; you'd
    never use them in cases where you knew the real type.

    --
    James
     
    James Kanze, May 31, 2013
    #8
  9. engineer

    Öö Tiib Guest

    On Friday, 31 May 2013 17:19:07 UTC+3, James Kanze wrote:
    > On Friday, May 31, 2013 10:05:28 AM UTC+1, Öö Tiib wrote:
    > > On Friday, 31 May 2013 11:33:18 UTC+3, Jorgen Grahn wrote:
    > > > Of course, many would say that in ideal world you don't see a lot of
    > > > typedef:ed pointers either. They are a source of confusion too.

    >
    > > Can you describe the situation where those many would say that?

    >
    > > For example: All C++ standard library containers (and some non-containers)
    > > have 'pointer' and 'const_pointer' member typedefs. Some non-containers
    > > have such typedefs as well. Some people ignore these, some use.
    > > Lack of such typedefs (in a weakly made custom container) may cause
    > > inconvenience for people who expect such typedefs ... but what confusion?

    >
    > The situation is a bit different there. 'pointer' and
    > 'const_pointer' are *not* necessarily T* and T const*.


    It is guaranteed to be something that works like pointer. It on most cases
    is actually pointer (besides vector<bool> and when using some fancy
    allocator).

    > And the typedef's are really only for use in template functions;
    > you'd never use them in cases where you knew the real type.


    It does not always matter that you know the real type. For example
    'Names' are typedefed 'std::vector<Name>'. Then it happens that you
    need a pointer 'n' to element of 'Names' for whatever reason. The
    purpose is cleaner (and maintenance easier) if you declare it as
    'Names::pointer' instead of 'Name*' despite you know that these
    are very same type.
     
    Öö Tiib, May 31, 2013
    #9
  10. engineer

    James Kanze Guest

    On Friday, May 31, 2013 4:41:29 PM UTC+1, Öö Tiib wrote:
    > On Friday, 31 May 2013 17:19:07 UTC+3, James Kanze wrote:
    > > On Friday, May 31, 2013 10:05:28 AM UTC+1, Öö Tiib wrote:
    > > > On Friday, 31 May 2013 11:33:18 UTC+3, Jorgen Grahn wrote:
    > > > > Of course, many would say that in ideal world you don't see a lot of
    > > > > typedef:ed pointers either. They are a source of confusion too.


    > > > Can you describe the situation where those many would say that?


    > > > For example: All C++ standard library containers (and some non-containers)
    > > > have 'pointer' and 'const_pointer' member typedefs. Some non-containers
    > > > have such typedefs as well. Some people ignore these, some use.
    > > > Lack of such typedefs (in a weakly made custom container) may cause
    > > > inconvenience for people who expect such typedefs ... but what confusion?


    > > The situation is a bit different there. 'pointer' and
    > > 'const_pointer' are *not* necessarily T* and T const*.


    > It is guaranteed to be something that works like pointer. It on most cases
    > is actually pointer (besides vector<bool> and when using some fancy
    > allocator).


    The whole point of having the pointer typedef is that it may not
    be a pointer. Or it may be some special type of pointer: all of
    these typedef's were introduced to support things like __huge
    (or whatever it was) on architectures where pointers could be
    declared to have different sizes. Without allocators, the
    typedef wouldn't be there.

    > > And the typedef's are really only for use in template functions;
    > > you'd never use them in cases where you knew the real type.


    > It does not always matter that you know the real type. For example
    > 'Names' are typedefed 'std::vector<Name>'. Then it happens that you
    > need a pointer 'n' to element of 'Names' for whatever reason. The
    > purpose is cleaner (and maintenance easier) if you declare it as
    > 'Names::pointer' instead of 'Name*' despite you know that these
    > are very same type.


    The code is considerably more readable if you use Name*, rather
    than Names::pointer (and if you use std::vector<Name>, rather
    than Names). Maintainable is a point of view: using Names
    and Names::pointer has the advantage of not requiring any other
    changes (hopefully) if you do later change to use a custom
    allocator. Otherwise, it's just obfuscation.

    --
    James
     
    James Kanze, Jun 2, 2013
    #10
  11. engineer

    Öö Tiib Guest

    On Sunday, 2 June 2013 16:40:35 UTC+3, James Kanze wrote:
    > On Friday, May 31, 2013 4:41:29 PM UTC+1, Öö Tiib wrote:
    > > It does not always matter that you know the real type. For example
    > > 'Names' are typedefed 'std::vector<Name>'. Then it happens that you
    > > need a pointer 'n' to element of 'Names' for whatever reason. The
    > > purpose is cleaner (and maintenance easier) if you declare it as
    > > 'Names::pointer' instead of 'Name*' despite you know that these
    > > are very same type.

    >
    > The code is considerably more readable if you use Name*, rather
    > than Names::pointer (and if you use std::vector<Name>, rather
    > than Names). Maintainable is a point of view: using Names
    > and Names::pointer has the advantage of not requiring any other
    > changes (hopefully) if you do later change to use a custom
    > allocator. Otherwise, it's just obfuscation.


    The bloat that results when using some relatively well performing
    container without typedefs is too lot for my simple mind. Consider:

    boost::intrusive::multiset< Thing, boost::intrusive::member_hook<Thing, boost::intrusive::set_member_hook<>, &Thing::member_hook_> > things;

    For me it is hard like that to use that type and to read code that
    uses that type. IOW we better remain on different opinions here.
    Readability depends on reader. Different readers have different
    capabilities.
     
    Öö Tiib, Jun 2, 2013
    #11
  12. engineer

    Jorgen Grahn Guest

    On Fri, 2013-05-31, James Kanze wrote:
    > On Friday, May 31, 2013 9:33:18 AM UTC+1, Jorgen Grahn wrote:
    >> On Wed, 2013-05-29, James Kanze wrote:
    >> > On Tuesday, May 28, 2013 10:30:39 AM UTC+1, engineer wrote:
    >> >> Can someone give me an easy explanation as well as the
    >> >> difference between the following three statements.

    >
    >> >> const char* p
    >> >> char const* m
    >> >> char* const n

    >
    >> > Just apply the general rule: const applies to whatever is
    >> > immediately to the left of it. If nothing is to the immediate
    >> > left of it, move it to the right until there is something.
    >> > Thus:

    >
    >> > const char* p; // The same as char const* p (which would be preferable)
    >> > char const* m; // (non-const) pointer to const char.
    >> > char *const n; // Const pointer to (non-const) char.
    >> > char const* const* o; // Const pointer to const char.

    >
    >> > In an ideal world, you'd never see the first declaration you
    >> > give, as it leads to a great deal of confusion when typedefs are
    >> > involved:

    >
    >> > typedef char* CPtr;
    >> > CPtr const p1; // char *const p1
    >> > const CPtr p2; // char *const p2 !!!

    >
    >> I think you're wrong here -- the const cannot "invade" the typedef, so
    >> both p1 and p2 are constant pointers to non-const stuff, like you'd
    >> expect.

    >
    > That's what I said, no?


    Oops, sorry! Yes, you did. I saw a claim that wasn't there, namely
    that 'const CPtr' and 'CPtr const' would be different things.

    I think my misunderstanding was 70% sloppy reading and 30% not being
    prepared for the claim that the actual behavior is confusing.
    (Although it would be if you mentally expand CPtr to "char *".)

    >> Of course, many would say that in ideal world you don't see a lot of
    >> typedef:ed pointers either. They are a source of confusion too.

    >
    > I'm tempted to say "wishful thinking".


    Yes, that's what "ideal world" means. But they are actually quite rare
    in the code I work with. There may be other ecosystems where they are
    common though.

    /Jorgen

    --
    // Jorgen Grahn <grahn@ Oo o. . .
    \X/ snipabacken.se> O o .
     
    Jorgen Grahn, Jun 3, 2013
    #12
  13. engineer

    Jorgen Grahn Guest

    On Mon, 2013-06-03, Scott Lurndal wrote:
    > Leigh Johnston <> writes:
    >>On 31/05/2013 15:16, James Kanze wrote:
    >>> On Friday, May 31, 2013 9:33:18 AM UTC+1, Jorgen Grahn wrote:
    >>>> Of course, many would say that in ideal world you don't see a lot of
    >>>> typedef:ed pointers either. They are a source of confusion too.
    >>>
    >>> I'm tempted to say "wishful thinking". I agree that typedef'ing
    >>> pointers is bad policy. But the same problems occur in more
    >>> complicated cases, where people are typedef'ing pointers to
    >>> member functions, or whatever. (Of course, I would argue that
    >>> even then, typedef's cause confusion. But given the syntax,
    >>> people do want to do it.)

    >>
    >>Wrong. typedef is great, use typedef as much as possible! As far as
    >>pointers are concerned: use pointers as little as possible!


    Disagree ...

    If you're thinking of 'typedef unsigned TcpPort;' and such, I prefer
    to create small wrapper classes. The typedef gives you a meaningful
    name; the class also gives you type safety ('port = date + 1' won't
    compile unless you tell it to).

    > The _only_ time typedef should be used in C++ code is when a C-type
    > function pointer "type" is required.


    Disagree ...

    > They should never be used with
    > structs (e.g. typedef struct {} xx_t;), since struct names are equiv to typedef
    > in C++. Likewise with enum.
    >
    > If you're using a pointer, don't hide the declaration in a macro or typedef;
    > why make the maintenance programmer go lookup what the typedef is?


    Agreed. But these are examples of typedef in C-like scenarios only.
    Typedef is important in classes and templates.

    /Jorgen

    --
    // Jorgen Grahn <grahn@ Oo o. . .
    \X/ snipabacken.se> O o .
     
    Jorgen Grahn, Jun 4, 2013
    #13
    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. Thomas Matthews
    Replies:
    5
    Views:
    2,484
    tom_usenet
    Aug 2, 2004
  2. Santa
    Replies:
    1
    Views:
    1,120
    Mark A. Odell
    Jul 17, 2003
  3. Replies:
    24
    Views:
    854
    Netocrat
    Oct 30, 2005
  4. lovecreatesbeauty
    Replies:
    1
    Views:
    1,096
    Ian Collins
    May 9, 2006
  5. Javier
    Replies:
    2
    Views:
    584
    James Kanze
    Sep 4, 2007
Loading...

Share This Page