Topic: ISO C++ forbids cast to non-reference type used as lvalue


Author: "Bury Huang" <buryhuang@gmail.com>
Date: Wed, 22 Feb 2006 09:53:02 CST
Raw View
Dear,

case 1:
  void * ptr = 0;
  (char *) ptr+=10;
warning: ANSI C++ forbids cast to non-reference type used as lvalue

case 2:
  char* ptr = 0;
  (char*)ptr +=10;
error: non-lvalue in assignment

case 3:
  char * ptr = 0;
  ptr +=10;
passed.

  I'm wondering why they're treaded different in C++.
  Can anyone tell me the underlying reason of making the decision of
making them different? What's the harms if case 1 and case2 are
allowed?

  In my opinion, since pointer is deemed to be allowed for arithmetic
calculation (+,-), all those resulted (char*) type should be able to
perform the same set of operation that original char* pointer can
perform.

Thanks a lot.

---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html                       ]





Author: "Andrew Koenig" <ark@acm.org>
Date: Wed, 22 Feb 2006 10:09:03 CST
Raw View
"Bury Huang" <buryhuang@gmail.com> wrote in message
news:1140596941.765338.200370@g14g2000cwa.googlegroups.com...

> case 1:
>  void * ptr = 0;
>  (char *) ptr+=10;
> warning: ANSI C++ forbids cast to non-reference type used as lvalue

> case 2:
>  char* ptr = 0;
>  (char*)ptr +=10;
> error: non-lvalue in assignment

> case 3:
>  char * ptr = 0;
>  ptr +=10;
> passed.

>  I'm wondering why they're treaded different in C++.
>  Can anyone tell me the underlying reason of making the decision of
> making them different? What's the harms if case 1 and case2 are
> allowed?

What would you like these operations to do?  Before you answer, here's an
analogous example:

    case 4:
        int n = 0;
        (float) n += 1.5;

What value would you like n to have after these statements are executed, and
why?

---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html                       ]





Author: clarkcox3@gmail.com ("Clark S. Cox III")
Date: Wed, 22 Feb 2006 19:48:55 GMT
Raw View
On 2006-02-22 04:53:02 -0500, "Bury Huang" <buryhuang@gmail.com> said:

> Dear,
>
> case 1:
>   void * ptr = 0;
>   (char *) ptr+=10;
> warning: ANSI C++ forbids cast to non-reference type used as lvalue
>
> case 2:
>   char* ptr = 0;
>   (char*)ptr +=10;
> error: non-lvalue in assignment
>
> case 3:
>   char * ptr = 0;
>   ptr +=10;
> passed.
>
>   I'm wondering why they're treaded different in C++.
>   Can anyone tell me the underlying reason of making the decision of
> making them different? What's the harms if case 1 and case2 are
> allowed?

What you are trying to do is equivalent to:
  struct Foo
  {
    int i_;
    Foo(int i) : i_(i) {}
  };

  Foo foo(0);
  (int)foo += 10;

or:
  int i=0;
  (double)i += 3.14159;

Do you expect those to work as well? (and how would you expect them to work?)

--
Clark S. Cox, III
clarkcox3@gmail.com

---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html                       ]





Author: johnchx2@yahoo.com
Date: Wed, 22 Feb 2006 22:13:45 CST
Raw View
Bury Huang wrote:
>   In my opinion, since pointer is deemed to be allowed for arithmetic
> calculation (+,-), all those resulted (char*) type should be able to
> perform the same set of operation that original char* pointer can
> perform.

The problem isn't the arithmetic operation, it's where you're trying to
store the result.  A cast to a non-reference type is an rvalue:  it
does NOT refer to the storage location of the "castee."  Typically, it
refers to no storage location at all (i.e. the result of the cast may
simply live in a register, with no address in memory).

You can get the result you want simply by casting to a reference type:

   char data[20];
   char* p = data;
   (char* &) p += 10;  // reference-to-char*

or don't use the cast on the result:

   char data[20];
   char* p = data;
   p =  (char*) p + 10;

---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html                       ]





Author: "Bury Huang" <buryhuang@gmail.com>
Date: Wed, 22 Feb 2006 22:14:58 CST
Raw View
thanks  Andrew and Clark

   I now understand the harms the casted l-value do.

   And, here comes another answer:
a.cpp:9: error: ISO C++ forbids cast to non-reference type used as
lvalue

   Why only "non-reference" are denied. Why a reference is allowed?

case 5
   int n = 0;
   (double &)n += 10.5;

   I think the reason is "n" is not modifed anyway. This operation
doesn't affect the subsequential operations.

Thanks a lot for your attentions.
Bury


"Clark S. Cox III"

> On 2006-02-22 04:53:02 -0500, "Bury Huang" <buryhuang@gmail.com> said:
>
> > Dear,
> >
> > case 1:
> >   void * ptr = 0;
> >   (char *) ptr+=10;
> > warning: ANSI C++ forbids cast to non-reference type used as lvalue
> >
> > case 2:
> >   char* ptr = 0;
> >   (char*)ptr +=10;
> > error: non-lvalue in assignment
> >
> > case 3:
> >   char * ptr = 0;
> >   ptr +=10;
> > passed.
> >
> >   I'm wondering why they're treaded different in C++.
> >   Can anyone tell me the underlying reason of making the decision of
> > making them different? What's the harms if case 1 and case2 are
> > allowed?
>
> What you are trying to do is equivalent to:
>   struct Foo
>   {
>     int i_;
>     Foo(int i) : i_(i) {}
>   };
>
>   Foo foo(0);
>   (int)foo += 10;
>
> or:
>   int i=0;
>   (double)i += 3.14159;
>
> Do you expect those to work as well? (and how would you expect them to work?)
>
> --
> Clark S. Cox, III
> clarkcox3@gmail.com
>
> ---
> [ comp.std.c++ is moderated.  To submit articles, try just posting with ]
> [ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
> [              --- Please see the FAQ before posting. ---               ]
> [ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html                       ]


---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html                       ]





Author: johnchx2@yahoo.com
Date: Thu, 23 Feb 2006 10:16:49 CST
Raw View
Bury Huang wrote:

>    Why only "non-reference" are denied. Why a reference is allowed?
>
> case 5
>    int n = 0;
>    (double &)n += 10.5;
>

It is legal to form the expression "(double&) n", which is an lvalue
which refers to the same object as n, but with a different type
(double) (5.2.10/10).

Where you run into trouble is when you try to use the expression:
3.10/15 says that it is undefined behavior to access the stored value
of an object through an lvalue of different type (with some exceptions,
none of which apply here).

Basically, the language doesn't guarantee that this will do anything
reasonable.  As with most uses of reinterpret_cast (which is what the
C-style cast gives you in this context), you're on thin,
platform-dependent ice.

---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html                       ]





Author: kuyper@wizard.net
Date: Thu, 23 Feb 2006 13:11:22 CST
Raw View
Bury Huang wrote:
.
>    And, here comes another answer:
> a.cpp:9: error: ISO C++ forbids cast to non-reference type used as
> lvalue
>
>    Why only "non-reference" are denied. Why a reference is allowed?
>
> case 5
>    int n = 0;
>    (double &)n += 10.5;

The above code is essentially equivalent to

*((double*)&n) += 10.5;

There is real object at the location pointed at by &n; If it's
sufficiently large and correctly alligned to hold a double, and
currently contains a valid representation of a double, that code could
actually do something useful. It could read that representation and
interpret it as a double, add 10.5 to it, and then store that result in
that same location. Type punning like this is always dangerous, and
seldom justified, but it is legal in some  contexts, such as making use
of memory allocated with malloc(), which is guaranteed to be suitably
aligned.

>    I think the reason is "n" is not modifed anyway.

Actually, as I understand it, 'n' would be modified by such code.

.
> "Clark S. Cox III"
>
> > On 2006-02-22 04:53:02 -0500, "Bury Huang" <buryhuang@gmail.com> said:
.
> > > case 1:
> > >   void * ptr = 0;
> > >   (char *) ptr+=10;

In contrast, this code creates an unnamed temporary object of type
char* by conversion from ptr. It reads the value of that temporary,
adds 10 to that number, and then saves the result in that temporary -
at least, that's what the code would mean, if it were legal. That's why
it's illegal - it's pointless to allow such code.


---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html                       ]





Author: "Bury Huang" <buryhuang@gmail.com>
Date: Mon, 27 Feb 2006 19:56:26 CST
Raw View
Thank guys.

Yes, I did make the mistake for " I think the reason is "n" is not
modifed anyway. "

Now I understand more about the tricky (double &)n. I agree with what
it means.

So the result would be : to make it compatible with some C style usages
as Kuy mentioned. And I agree "it's pointless to allow such code."
Because, even pointer can be more readable than "(double &)n"

If this understanding correct?
If so, can someone suggest C++ to disallow "reference" to be used
l-value?

Thanks

---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html                       ]