void* used in arithmetics

Collapse
This topic is closed.
X
X
 
  • Time
  • Show
Clear All
new posts
  • Xavier Decoret

    void* used in arithmetics

    This is a compiler error that I get when I try to do:

    void* p;
    unsigned int stride;
    // ...
    p += stride;


    I have good reason to do this, namely an iterator over an array of
    object whose type may vary, as outlined below. So I don't understand why
    it is a compiler error and not only a warning. I can superced this by:
    p = ((char*) p)+1;
    but I don't like it.

    class Type;
    class TypeA : public Type; // has as sizeof 10 for example
    class TypeB : public Type; // has as sizeof 20 for example

    class Parent
    {
    public:
    class Iterator
    {
    public:
    Type* operator->() const { return reinterpret_cas t<Type*>(p_); }
    Iterator& operator++() { p_ += stride_; return *this; }
    protected:
    friend class Parent;
    Iterator(void* p,int s) : p_(p),stride_(s ) {}
    private:
    void* p_;
    int stride_;
    }
    protected:
    template <class T>
    Iterator iterator(const T* t)
    {
    return Iterator(t,size of(T));
    }
    };


    Then I can have sublclasses of Parent using vectors of TypeA or TypeB on
    which I can iterate using the Type interface thru the Parent interface.

    --
    +-------------------------------------------------+
    | Xavier Décoret - Post Doct |
    | Graphics Lab (LCS) - MIT |
    | mailto: decoret@graphic s.lcs.mit.edu |
    | home : http://www.graphics.lc s.mit.edu/~decoret|
    +-------------------------------------------------+

  • Jack Klein

    #2
    Re: void* used in arithmetics

    On Sat, 19 Jul 2003 00:47:38 -0400, Xavier Decoret
    <decoret@graphi cs.lcs.mit.edu> wrote in comp.lang.c++:
    [color=blue]
    > This is a compiler error that I get when I try to do:
    >
    > void* p;
    > unsigned int stride;
    > // ...
    > p += stride;
    >
    >
    > I have good reason to do this, namely an iterator over an array of
    > object whose type may vary, as outlined below. So I don't understand why
    > it is a compiler error and not only a warning. I can superced this by:
    > p = ((char*) p)+1;
    > but I don't like it.[/color]

    Your reasons might or might not be good, but neither C nor C++ have
    ever allowed this, and they never will. A pointer is not just a
    number, it has additional qualities, namely the size of the type
    pointed to.

    If you add 1 to a pointer to char, the pointer points to the next char
    (next byte).

    But if you add 1 to a pointer to int, the pointer points to the next
    int, so the actual address increases by sizeof(int). If you have a
    pointer to a struct or a class with a size of 10 bytes, adding 1 to
    that pointer causes the actual memory location pointed to to change by
    10 bytes.

    Pointers are not integer types, and do not behave like integer types.

    To perform arithmetic on any pointer type, it must be a pointer to a
    complete type, meaning that the compiler must have a definition for
    the type in scope from which it can determine the size of the type.

    "void" is an incomplete type which cannot be completed.

    You can't perform arithmetic on pointers to any incomplete type.
    That's just the way it is, the way it has always been, and almost
    certainly the way it's going to stay.

    Pointers to the character types are pointers to complete types, and
    objects of these types (signed, unsigned, or "plain" char) are
    ordinary bytes. The conversion of a pointer to void into a pointer to
    any of the character types is guaranteed to leave the representation
    unchanged, and then you can do arithmetic using the size of objects,
    which is also expressed in terms of bytes.
    [color=blue]
    > class Type;
    > class TypeA : public Type; // has as sizeof 10 for example
    > class TypeB : public Type; // has as sizeof 20 for example
    >
    > class Parent
    > {
    > public:
    > class Iterator
    > {
    > public:
    > Type* operator->() const { return reinterpret_cas t<Type*>(p_); }
    > Iterator& operator++() { p_ += stride_; return *this; }
    > protected:
    > friend class Parent;
    > Iterator(void* p,int s) : p_(p),stride_(s ) {}
    > private:
    > void* p_;
    > int stride_;
    > }
    > protected:
    > template <class T>
    > Iterator iterator(const T* t)
    > {
    > return Iterator(t,size of(T));
    > }
    > };
    >
    >
    > Then I can have sublclasses of Parent using vectors of TypeA or TypeB on
    > which I can iterate using the Type interface thru the Parent interface.[/color]

    If you want to perform this sort of low-level pointer manipulation you
    have no choice but to convert to pointer to one of the character
    types. The language does not allow adding integers to pointer to void
    because it would have to multiply the integer by sizeof(void), which
    is not defined.

    --
    Jack Klein
    Home: http://JK-Technology.Com
    FAQs for
    comp.lang.c http://www.eskimo.com/~scs/C-faq/top.html
    comp.lang.c++ http://www.parashift.com/c++-faq-lite/
    alt.comp.lang.l earn.c-c++ ftp://snurse-l.org/pub/acllc-c++/faq

    Comment

    • John Dibling

      #3
      Re: void* used in arithmetics

      >object whose type may vary, as outlined below. So I don't understand why[color=blue]
      >it is a compiler error and not only a warning. I can superced this by:[/color]

      Because the compiler doesn't know how far to move the pointer. If the
      void* is an array of char, it would move it 1 byte for every
      increment. On the other hand, if the void* points to an array of
      double, it wouldn't have to move by one byte anymore, because a double
      takes more than 1 byte of memory.

      You must cast as you did in your sample. Sorry you don't like it, but
      that the glamorous life of a C++ programmer...

      </dib>

      John Dibling
      email: dib@substitute_ my_full_last_na me_here.com
      Witty banter omitted for your protection

      Comment

      Working...