declaring functions moving input pointer

Discussion in 'C Programming' started by Ilya N. Golubev, Aug 24, 2006.

  1. There is already one function processing pointer values this way. And
    there may easily appear more, including wrappers for this function.

    For purposes of further discussion, consider simplified function,
    `consume'. It has one arg, INBUF, that points to a variable that
    points to the first character in the input buffer. The function never
    modifies characters pointed to by `*INBUF'. It, however, updates
    the `*INBUF' value to point to the byte following the last byte
    successfully consumed.

    We can declare this function

    void consume (const char **);

    or

    void consume (char **);

    Which one is appropriate, wrt semantics of `const' as designed in
    current C language standards? In any case, applications may have both
    `char *' and `const char *' variables, which must be passed and
    updated as described above. In any case, the conversions are be
    needed to do such a passing, like this.

    void consume (const char **);
    /* ... */
    char *buf;
    consume ((const char **) &buf);

    Or

    void consume (char **);
    /* ... */
    const char *buf;
    consume ((char **) &buf);

    Currently, if T is type, any `T*' value may be assigned to `const T*'
    one. This is not the case for assigning `T**' values to `const T**'
    ones. Why would allowing this be incorrect / dangerous?

    Or should we completely avoid declaring functions with `**' args like
    these, and specify them like `write' instead? That is, to take `const
    char *' arg and return or otherwise pass to caller a `ssize_t' value
    saying how much should be added to said `const char *' value before
    passing it to the next call.


    The function needs to update `size_t' value in addition to `char *'
    one anyway, and this should be also the case for its wrappers. So one
    might declare `consume' like this.

    typedef struct {
    const char *p;
    size_t s;
    } ciov_t;
    void consume (ciov_t *IR);

    So that is updates both `IR->p' and `IR->s'.

    Never seen such a declarations, however. `writev', in particular,
    does not use input structures with `const void *' for data to write.
    This will even cause trouble for application writers needing to pass
    such a data pointers to `writev'. What would be dangerous / incorrect
    in declaring functions this way?
     
    Ilya N. Golubev, Aug 24, 2006
    #1
    1. Advertising

  2. Ilya N. Golubev

    Michael Mair Guest

    Ilya N. Golubev schrieb:
    > There is already one function processing pointer values this way. And
    > there may easily appear more, including wrappers for this function.
    >
    > For purposes of further discussion, consider simplified function,
    > `consume'. It has one arg, INBUF, that points to a variable that
    > points to the first character in the input buffer. The function never
    > modifies characters pointed to by `*INBUF'. It, however, updates
    > the `*INBUF' value to point to the byte following the last byte
    > successfully consumed.
    >
    > We can declare this function
    >
    > void consume (const char **);
    >
    > or
    >
    > void consume (char **);
    >
    > Which one is appropriate, wrt semantics of `const' as designed in
    > current C language standards? In any case, applications may have both
    > `char *' and `const char *' variables, which must be passed and
    > updated as described above. In any case, the conversions are be
    > needed to do such a passing, like this.
    >
    > void consume (const char **);
    > /* ... */
    > char *buf;
    > consume ((const char **) &buf);
    >
    > Or
    >
    > void consume (char **);
    > /* ... */
    > const char *buf;
    > consume ((char **) &buf);
    >
    > Currently, if T is type, any `T*' value may be assigned to `const T*'
    > one. This is not the case for assigning `T**' values to `const T**'
    > ones. Why would allowing this be incorrect / dangerous?


    Have a look at the comp.lang.c FAQ, especially
    http://c-faq.com/ansi/constmismatch.html

    BTW: I'd rather use the "secure" form of "const char **" and have
    no cast, i.e.
    char *buf;
    const char *cbuf;
    ....
    cbuf = buf;
    consume(&cbuf);
    Avoiding the cast can help you find errors like
    consume(cbuf);
    which is not possible for
    consume((const char **)buf);

    > Or should we completely avoid declaring functions with `**' args like
    > these, and specify them like `write' instead? That is, to take `const
    > char *' arg and return or otherwise pass to caller a `ssize_t' value
    > saying how much should be added to said `const char *' value before
    > passing it to the next call.


    Note that in the context of standard C, there is no "ssize_t" but
    there is in POSIX. From the following, I guess that you really mean
    size_t.

    > The function needs to update `size_t' value in addition to `char *'
    > one anyway, and this should be also the case for its wrappers. So one
    > might declare `consume' like this.
    >
    > typedef struct {
    > const char *p;
    > size_t s;
    > } ciov_t;
    > void consume (ciov_t *IR);
    >
    > So that is updates both `IR->p' and `IR->s'.
    >
    > Never seen such a declarations, however. `writev', in particular,
    > does not use input structures with `const void *' for data to write.
    > This will even cause trouble for application writers needing to pass
    > such a data pointers to `writev'. What would be dangerous / incorrect
    > in declaring functions this way?


    I am not sure whether I understood you correctly.
    Do you want to modify data pointed to by a pointer to const type?
    This is most of the time a bad idea; if you can guarantee that
    you had a pointer to unqualified type to start with, then
    "removing the const" may work. If the data was const qualified
    from the start, it may well reside in some sort of non-writable
    memory.
    Or do you want to read data pointed to by IR->p?

    The "updates" throws me off, to be honest.

    Cheers
    Michael
    --
    E-Mail: Mine is an /at/ gmx /dot/ de address.
     
    Michael Mair, Aug 24, 2006
    #2
    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. darrel
    Replies:
    3
    Views:
    358
    Kevin Spencer
    Aug 13, 2004
  2. linkswanted
    Replies:
    0
    Views:
    946
    linkswanted
    Dec 21, 2007
  3. linkswanted
    Replies:
    0
    Views:
    1,578
    linkswanted
    Jan 6, 2008
  4. linkswanted
    Replies:
    0
    Views:
    454
    linkswanted
    Jan 23, 2008
  5. linkswanted
    Replies:
    0
    Views:
    638
    linkswanted
    Jan 24, 2008
Loading...

Share This Page