const, typedef, and warning

Discussion in 'C Programming' started by Michael Press, Nov 30, 2010.

  1. The following code compiles with a warning this way

    cc -c -DWHICH=1 try.c

    try.c: In function 'foo':
    try.c:12: warning: initialization discards qualifiers from pointer target type

    and without a warning this way.

    cc -c -DWHICH=2 try.c

    What gives? Why can I not use my typedef pst?


    ___________________BEGIN___________________
    typedef struct
    {
    int a;
    int b;
    } st;

    typedef st *pst;

    int foo(const void *x)
    {
    #if WHICH == 1
    const pst s = x;
    #elif WHICH == 2
    const st *s = x;
    #endif
    }

    int main(void)
    {
    pst arr;

    foo(arr);
    return 0;
    }
    ____________________END____________________

    --
    Michael Press
    Michael Press, Nov 30, 2010
    #1
    1. Advertising

  2. In article
    <>,
    Peter Nilsson <> wrote:

    > On Nov 30, 1:48 pm, Michael Press <> wrote:
    > > The following code compiles with a warning this way
    > >
    > >     cc -c -DWHICH=1 try.c
    > >
    > > try.c: In function 'foo':
    > > try.c:12: warning: initialization discards qualifiers from
    > > pointer target type
    > >
    > > and without a warning this way.
    > >
    > >     cc -c -DWHICH=2 try.c
    > >
    > > What gives? Why can I not use my typedef pst?
    > >
    > > ___________________BEGIN___________________
    > > typedef struct
    > > {
    > >     int a;
    > >     int b;
    > > } st;
    > >
    > > typedef st *pst;
    > >
    > > int foo(const void *x)
    > > {
    > > #if   WHICH == 1
    > >     const pst  s = x;

    >
    > This defines a constant pointer to a non-constant struct.
    >
    > > #elif WHICH == 2
    > >     const  st *s = x;

    >
    > This defines a non-constant pointer to a constant struct.
    >
    > > #endif
    > >
    > > }

    > <snip>


    Thanks, I see. The following compiles without a warning,
    for instance.

    typedef const st *pcst;

    int foo(const void *x)
    {
    pcst s = x;

    ....

    --
    Michael Press
    Michael Press, Nov 30, 2010
    #2
    1. Advertising

  3. On Nov 30, 1:48 pm, Michael Press <> wrote:
    > The following code compiles with a warning this way
    >
    >     cc -c -DWHICH=1 try.c
    >
    > try.c: In function 'foo':
    > try.c:12: warning: initialization discards qualifiers from
    > pointer target type
    >
    > and without a warning this way.
    >
    >     cc -c -DWHICH=2 try.c
    >
    > What gives? Why can I not use my typedef pst?
    >
    > ___________________BEGIN___________________
    > typedef struct
    > {
    >     int a;
    >     int b;
    > } st;
    >
    > typedef st *pst;
    >
    > int foo(const void *x)
    > {
    > #if   WHICH == 1
    >     const pst  s = x;


    This defines a constant pointer to a non-constant struct.

    > #elif WHICH == 2
    >     const  st *s = x;


    This defines a non-constant pointer to a constant struct.

    > #endif
    >
    > }

    <snip>

    --
    Peter
    Peter Nilsson, Nov 30, 2010
    #3
  4. Michael Press

    Ian Collins Guest

    On 11/30/10 04:13 PM, Michael Press wrote:
    >
    > Thanks, I see. The following compiles without a warning,
    > for instance.
    >
    > typedef const st *pcst;
    >
    > int foo(const void *x)
    > {
    > pcst s = x;


    Your post is a good example why typedefs for pointer types are seldom a
    good idea!

    --
    Ian Collins
    Ian Collins, Nov 30, 2010
    #4
  5. In article <>,
    Ian Collins <> wrote:

    > On 11/30/10 04:13 PM, Michael Press wrote:
    > >
    > > Thanks, I see. The following compiles without a warning,
    > > for instance.
    > >
    > > typedef const st *pcst;
    > >
    > > int foo(const void *x)
    > > {
    > > pcst s = x;

    >
    > Your post is a good example why typedefs for pointer types are seldom a
    > good idea!


    Yes. When are they a good idea?
    You may have guessed that my
    difficulty arose passing a
    function pointer to qsort.

    --
    Michael Press
    Michael Press, Nov 30, 2010
    #5
  6. Michael Press

    BartC Guest

    "Ian Collins" <> wrote in message
    news:...
    > On 11/30/10 04:13 PM, Michael Press wrote:
    >>
    >> Thanks, I see. The following compiles without a warning,
    >> for instance.
    >>
    >> typedef const st *pcst;
    >>
    >> int foo(const void *x)
    >> {
    >> pcst s = x;

    >
    > Your post is a good example why typedefs for pointer types are seldom a
    > good idea!


    Or use of 'const', which seems to be causing the problems.

    --
    Bartc
    BartC, Nov 30, 2010
    #6
  7. "BartC" <> writes:
    > "Ian Collins" <> wrote in message
    > news:...
    >> On 11/30/10 04:13 PM, Michael Press wrote:
    >>>
    >>> Thanks, I see. The following compiles without a warning,
    >>> for instance.
    >>>
    >>> typedef const st *pcst;
    >>>
    >>> int foo(const void *x)
    >>> {
    >>> pcst s = x;

    >>
    >> Your post is a good example why typedefs for pointer types are seldom a
    >> good idea!

    >
    > Or use of 'const', which seems to be causing the problems.


    It's the mis-use of 'const' that's causing the problems. const
    can be difficult to use correctly, but it's very useful when used
    correctly.

    --
    Keith Thompson (The_Other_Keith) <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"
    Keith Thompson, Nov 30, 2010
    #7
  8. In article <id31kq$mtf$-september.org>,
    "BartC" <> wrote:

    > "Ian Collins" <> wrote in message
    > news:...
    > > On 11/30/10 04:13 PM, Michael Press wrote:
    > >>
    > >> Thanks, I see. The following compiles without a warning,
    > >> for instance.
    > >>
    > >> typedef const st *pcst;
    > >>
    > >> int foo(const void *x)
    > >> {
    > >> pcst s = x;

    > >
    > > Your post is a good example why typedefs for pointer types are seldom a
    > > good idea!

    >
    > Or use of 'const', which seems to be causing the problems.


    I have to use it calling the library qsort.
    No reason why I cannot write my own sort.
    Heapsort is simple to write but slower than
    quicksort, and quicksort is more difficult
    to write. Now I still have the problem of
    a compare routine that modifies what is to
    be sorted, and that is solved with const.
    Or I could turn off warnings, but that is
    against my religion.

    --
    Michael Press
    Michael Press, Nov 30, 2010
    #8
  9. Michael Press

    ImpalerCore Guest

    On Nov 30, 2:36 pm, Michael Press <> wrote:
    > In article <id31kq$-september.org>,
    >
    >
    >
    >  "BartC" <> wrote:
    > > "Ian Collins" <> wrote in message
    > >news:...
    > > > On 11/30/10 04:13 PM, Michael Press wrote:

    >
    > > >> Thanks, I see. The following compiles without a warning,
    > > >> for instance.

    >
    > > >> typedef const st *pcst;

    >
    > > >> int foo(const void *x)
    > > >> {
    > > >>      pcst s  = x;

    >
    > > > Your post is a good example why typedefs for pointer types are seldom a
    > > > good idea!

    >
    > > Or use of 'const', which seems to be causing the problems.

    >
    > I have to use it calling the library qsort.
    > No reason why I cannot write my own sort.
    > Heapsort is simple to write but slower than
    > quicksort, and quicksort is more difficult
    > to write. Now I still have the problem of
    > a compare routine that modifies what is to
    > be sorted, and that is solved with const.
    > Or I could turn off warnings, but that is
    > against my religion.


    To avoid dealing with the issue you encountered, as a rule I have
    found it best not to define typedefs to pointer types at all. I value
    being able to use const properly more than defining shortcuts to
    declare pointer types.

    However, I still like using typedefs for function pointer types.
    ImpalerCore, Nov 30, 2010
    #9
  10. Michael Press

    Nobody Guest

    On Tue, 30 Nov 2010 00:09:01 -0700, Michael Press wrote:

    >> Your post is a good example why typedefs for pointer types are seldom a
    >> good idea!

    >
    > Yes. When are they a good idea?


    They can be useful for opaque types, e.g.:

    struct internal_data;
    typedef struct internal_data *handle_t;
    Nobody, Dec 1, 2010
    #10
  11. Michael Press <> wrote:
    > "BartC" <> wrote:
    > > "Ian Collins" <> wrote:
    > > > Michael Press wrote:
    > > > > Thanks, I see. The following compiles without a warning,
    > > > > for instance.
    > > > >
    > > > > typedef const st *pcst;
    > > > >
    > > > > int foo(const void *x)
    > > > > {
    > > > >      pcst s  = x;
    > > >
    > > > Your post is a good example why typedefs for pointer types
    > > > are seldom a good idea!

    > >
    > > Or use of 'const', which seems to be causing the problems.

    >
    > I have to use it calling the library qsort.


    A better example would have made this clear.

    > No reason why I cannot write my own sort.


    Here's a contrived program that sorts words in the command
    line via qsort, and shows how many times qsort compared each
    word...

    % type wordsort.c
    #include <stdio.h>
    #include <stdlib.h>
    #include <string.h>

    struct word_t
    {
    const char *word_m;
    size_t count_m;
    };

    size_t word_count_g;
    size_t capacity_g;

    struct word_t **word_g;

    struct word_t *add_word(const char *word_p)
    {
    struct word_t *word;

    if (word_count_g == capacity_g)
    {
    struct word_t **new_word_g;

    if (capacity_g == 0)
    capacity_g = 16;
    else if (capacity_g > (size_t) -1 / sizeof *word_g)
    return 0;
    else capacity_g *= 2;

    new_word_g = realloc(word_g, capacity_g * sizeof *new_word_g);
    if (!new_word_g) return 0;
    word_g = new_word_g;
    }

    word = malloc(sizeof *word);
    if (!word) return 0;

    word->word_m = word_p;
    word->count_m = 0;

    return word_g[word_count_g++] = word;
    }

    int compare(const void *lv, const void *rv)
    {
    struct word_t * const *lwp = lv;
    struct word_t * const *rwp = rv;
    (*lwp)->count_m++;
    (*rwp)->count_m++;
    return strcmp((*lwp)->word_m, (*rwp)->word_m);
    }

    int main(int argc, char **argv)
    {
    int i;
    size_t n;

    for (i = 1; i < argc; i++)
    if (!add_word(argv))
    { fputs("out of memory\n", stderr);
    exit(EXIT_FAILURE); }

    qsort(word_g, word_count_g, sizeof *word_g, compare);

    for (n = 0; n < word_count_g; n++)
    printf("%s: %lu\n",
    word_g[n]->word_m,
    (unsigned long) word_g[n]->count_m);

    return 0;
    }

    % acc wordsort.c -o wordsort.exe

    % wordsort this is a small sentence of few words
    a: 3
    few: 6
    is: 6
    of: 5
    sentence: 5
    small: 5
    this: 7
    words: 1

    %

    --
    Peter
    Peter Nilsson, Dec 1, 2010
    #11
  12. Michael Press

    Eric Sosman Guest

    On 11/30/2010 7:22 PM, Nobody wrote:
    > On Tue, 30 Nov 2010 00:09:01 -0700, Michael Press wrote:
    >
    >>> Your post is a good example why typedefs for pointer types are seldom a
    >>> good idea!

    >>
    >> Yes. When are they a good idea?

    >
    > They can be useful for opaque types, e.g.:
    >
    > struct internal_data;
    > typedef struct internal_data *handle_t;


    I've used this -- and then I've backed away from it. It seems
    to me that the function

    handle_t getInternalData(const whatnot*);

    .... often needs to be able to return an "I couldn't find one" result.
    The "natural" thing to do in C is to return NULL (see malloc, fopen,
    getenv, strstr, ...), but telling the caller to compare the returned
    value to NULL "leaks the abstraction."

    Yes, one *could* supply

    #define HANDLE_NONE ( (handle_t)NULL )

    .... and tell the callers to compare against HANDLE_NONE, or one *could*
    provide

    #define HANDLE_IS_VALID(handle) ((handle) != NULL)

    .... and tell them to use it to test the returned value -- but, I mean,
    gosh, guys, how many self-invented hoops do you want to jump through
    just so you can show off your insteps?

    For opaque types, I find

    typedef struct_internal ThroughAGlassDarkly
    ThroughAGlassDarkly * whosTheFairestOfThemAll(void);

    .... to be far more "natural." YMMV.

    --
    Eric Sosman
    lid
    Eric Sosman, Dec 1, 2010
    #12
  13. Michael Press

    Ian Collins Guest

    On 12/ 1/10 03:38 PM, Eric Sosman wrote:
    > On 11/30/2010 7:22 PM, Nobody wrote:
    >> On Tue, 30 Nov 2010 00:09:01 -0700, Michael Press wrote:
    >>
    >>>> Your post is a good example why typedefs for pointer types are seldom a
    >>>> good idea!
    >>>
    >>> Yes. When are they a good idea?

    >>
    >> They can be useful for opaque types, e.g.:
    >>
    >> struct internal_data;
    >> typedef struct internal_data *handle_t;

    >
    > I've used this -- and then I've backed away from it. It seems
    > to me that the function
    >
    > handle_t getInternalData(const whatnot*);
    >
    > .... often needs to be able to return an "I couldn't find one" result.
    > The "natural" thing to do in C is to return NULL (see malloc, fopen,
    > getenv, strstr, ...), but telling the caller to compare the returned
    > value to NULL "leaks the abstraction."
    >
    > Yes, one *could* supply
    >
    > #define HANDLE_NONE ( (handle_t)NULL )
    >
    > .... and tell the callers to compare against HANDLE_NONE, or one *could*
    > provide
    >
    > #define HANDLE_IS_VALID(handle) ((handle) != NULL)
    >
    > .... and tell them to use it to test the returned value -- but, I mean,
    > gosh, guys, how many self-invented hoops do you want to jump through
    > just so you can show off your insteps?
    >
    > For opaque types, I find
    >
    > typedef struct_internal ThroughAGlassDarkly
    > ThroughAGlassDarkly * whosTheFairestOfThemAll(void);
    >
    > .... to be far more "natural." YMMV.


    The problem there is you can't declare an instance of a
    ThroughAGlassDarkly, only a pointer to one. I guess this is why opaque
    types tend to be pointers.

    --
    Ian Collins
    Ian Collins, Dec 1, 2010
    #13
  14. Michael Press

    Eric Sosman Guest

    On 11/30/2010 9:52 PM, Ian Collins wrote:
    > On 12/ 1/10 03:38 PM, Eric Sosman wrote:
    >> On 11/30/2010 7:22 PM, Nobody wrote:
    >>> On Tue, 30 Nov 2010 00:09:01 -0700, Michael Press wrote:
    >>>
    >>>>> Your post is a good example why typedefs for pointer types are
    >>>>> seldom a
    >>>>> good idea!
    >>>>
    >>>> Yes. When are they a good idea?
    >>>
    >>> They can be useful for opaque types, e.g.:
    >>>
    >>> struct internal_data;
    >>> typedef struct internal_data *handle_t;

    >>
    >> I've used this -- and then I've backed away from it. It seems
    >> to me that the function
    >>
    >> handle_t getInternalData(const whatnot*);
    >>
    >> .... often needs to be able to return an "I couldn't find one" result.
    >> The "natural" thing to do in C is to return NULL (see malloc, fopen,
    >> getenv, strstr, ...), but telling the caller to compare the returned
    >> value to NULL "leaks the abstraction."
    >>
    >> Yes, one *could* supply
    >>
    >> #define HANDLE_NONE ( (handle_t)NULL )
    >>
    >> .... and tell the callers to compare against HANDLE_NONE, or one *could*
    >> provide
    >>
    >> #define HANDLE_IS_VALID(handle) ((handle) != NULL)
    >>
    >> .... and tell them to use it to test the returned value -- but, I mean,
    >> gosh, guys, how many self-invented hoops do you want to jump through
    >> just so you can show off your insteps?
    >>
    >> For opaque types, I find
    >>
    >> typedef struct_internal ThroughAGlassDarkly
    >> ThroughAGlassDarkly * whosTheFairestOfThemAll(void);
    >>
    >> .... to be far more "natural." YMMV.

    >
    > The problem there is you can't declare an instance of a
    > ThroughAGlassDarkly, only a pointer to one. I guess this is why opaque
    > types tend to be pointers.


    What I'm saying is that the approach I prefer is to make the
    opaque type a struct (most likely) and to have all the functions
    that manage it deal in struct pointers. See, for example, the FILE
    type: Functions like fopen() that "create" such objects return
    pointers to them; functions that "consume" them accept pointers.
    You can't create a free-standing FILE instance -- well, you *can*
    because of what I suspect is an unintentional slip of the Standard,
    but even so, the free-standing FILE can't be used for I/O.

    That's the pattern I feel fits best with C -- except that I don't
    feel bound to imitate the Standard's accident and allow free-standing
    instances. One advantage of prohibiting free-standing instances is
    that you can change the implementation, including changing the size of
    an instance, without even recompiling the clients: All they get is a
    pointer, and they don't know or need to know how many bytes are on the
    other end of it.

    --
    Eric Sosman
    lid
    Eric Sosman, Dec 1, 2010
    #14
  15. In article
    <>,
    Peter Nilsson <> wrote:

    > Michael Press <> wrote:
    > > "BartC" <> wrote:
    > > > "Ian Collins" <> wrote:
    > > > > Michael Press wrote:
    > > > > > Thanks, I see. The following compiles without a warning,
    > > > > > for instance.
    > > > > >
    > > > > > typedef const st *pcst;
    > > > > >
    > > > > > int foo(const void *x)
    > > > > > {
    > > > > >      pcst s  = x;
    > > > >
    > > > > Your post is a good example why typedefs for pointer types
    > > > > are seldom a good idea!
    > > >
    > > > Or use of 'const', which seems to be causing the problems.

    > >
    > > I have to use it calling the library qsort.

    >
    > A better example would have made this clear.


    That was the best example, from my point of view.
    It elicited exactly the help I needed at that time:
    namely that I need to parse const as I parse other
    tokens in declarators; rather than trying to cobble
    together something that works by trial and error,
    as if const were an impediment to doing what I want.

    > Here's a contrived program that sorts words in the command
    > line via qsort, and shows how many times qsort compared each
    > word...


    Read, understood, and filed. Thank you.

    --
    Michael Press
    Michael Press, Dec 1, 2010
    #15
    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. Replies:
    14
    Views:
    693
    Kai-Uwe Bux
    Sep 18, 2006
  2. Replies:
    11
    Views:
    1,101
  3. Javier
    Replies:
    2
    Views:
    561
    James Kanze
    Sep 4, 2007
  4. 0m
    Replies:
    26
    Views:
    1,115
    Tim Rentsch
    Nov 10, 2008
  5. fungus
    Replies:
    13
    Views:
    887
    fungus
    Oct 31, 2008
Loading...

Share This Page