Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

Am i just blind? Is "array = array;" allowed?

36 views
Skip to first unread message

Johannes Schaub (litb)

unread,
Aug 27, 2010, 10:02:24 AM8/27/10
to
I really can't find where the Standard forbids the following!

int a[2] = { 1, 2 };
int b[2];
b = a;

I thought somewhere the Standard says that lvalue expressions of array type
are nonmodifiable, but I can't find it!

Any insights?

Goran Pusic

unread,
Aug 27, 2010, 10:19:35 AM8/27/10
to
On Aug 27, 4:02 pm, "Johannes Schaub (litb)" <schaub-johan...@web.de>
wrote:

No idea about what standard might think, but if it did think
something, it would still sound like a silly arbitrary constraint.
What would be the rationale to prevent said assignment?

Goran.

Jonathan Lee

unread,
Aug 27, 2010, 10:24:45 AM8/27/10
to
On Aug 27, 9:02 am, "Johannes Schaub (litb)" <schaub-johan...@web.de>
wrote:

In [dcl.array]

5. [Node: conversions affecting lvalues of array type are described in
4.2. Objects of array types cannot be modified, see 3.10 -- end note]

--Jonathan

Johannes Schaub (litb)

unread,
Aug 27, 2010, 10:31:14 AM8/27/10
to
Jonathan Lee wrote:

Sorry, i can't accept a note. I am looking for normative wording. Is there
any?

Leigh Johnston

unread,
Aug 27, 2010, 10:46:31 AM8/27/10
to

"Johannes Schaub (litb)" <schaub-...@web.de> wrote in message
news:i58i3h$58l$03$1...@news.t-online.com...

Why can't you accept a note?

/Leigh

Christian Hackl

unread,
Aug 27, 2010, 10:56:18 AM8/27/10
to
Johannes Schaub (litb) ha scritto:

> I really can't find where the Standard forbids the following!
>
> int a[2] = { 1, 2 };
> int b[2];
> b = a;

It should not compile. Does it on your compiler? I guess you are just
the victim of some proprietary extension.


--
Christian Hackl
ha...@sbox.tugraz.at

Milano 2008/2009 -- L'Italia chiamň, sě!

Alf P. Steinbach /Usenet

unread,
Aug 27, 2010, 10:59:42 AM8/27/10
to
* Johannes Schaub (litb), on 27.08.2010 16:31:

I don't think so, but I think it was intended.

C++98 §5/8 says that an array is converted to pointer when it's used where an
rvalue is expected.

Then §5.17/2 talks about the "value" of the right hand side of an assignment.

Cheers & hth.,

- Alf

--
blog at <url: http://alfps.wordpress.com>

Johannes Schaub (litb)

unread,
Aug 27, 2010, 11:40:52 AM8/27/10
to

Ohh i see now. So i guess it does the array-to-pointer conversion of the
right side, and then tries to convert "T*" to "T[N]" but since there is no
such implicit conversion, it fails hard. Thanks for the insights

Johannes Schaub (litb)

unread,
Aug 27, 2010, 11:39:47 AM8/27/10
to
Christian Hackl wrote:

> Johannes Schaub (litb) ha scritto:
>
>> I really can't find where the Standard forbids the following!
>>
>> int a[2] = { 1, 2 };
>> int b[2];
>> b = a;
>
> It should not compile. Does it on your compiler? I guess you are just
> the victim of some proprietary extension.
>

It compiles with my built-in biological compiler. It needs fixing my being
pointed to a normative text! AHAHAHA

Juha Nieminen

unread,
Aug 27, 2010, 12:17:09 PM8/27/10
to

It's not arbitrary at all, and there is a perfectly good rationale
which can be derived from the definition of arrays.

Arrays effectively act as const pointers (in other words "int* const"),
the only exception being that the sizeof() operator returns the space
taken by the entire array rather than the size of a pointer. (I know this
is simplifying quite a lot, and there are probably other examples where
they don't actually act like const pointers, but you get the idea.)

So you can think of "b = a;" as the attempt to modify 'b' to make it
point to the same place as 'a' is pointing to (because that's what pointer
assignment does). However, 'b' is const, so you can't modify it to point
anywhere else.

Of course one could argue that the language should make an exception
to this general principle in the case where you are assigning an array to
another of the same type and size, and make it instead assign the contents
of the array to the other array. I don't know, however, if the
standardization committee had a reason to not impose such an exception
to the general rule (and we are probably talking about the C standardization
committee here, as this limitation is probably coming from C).

Johannes Schaub (litb)

unread,
Aug 27, 2010, 12:32:10 PM8/27/10
to
Juha Nieminen wrote:

I would argue the entire other way around, and make the pointer behavior a
"special case":

>>>>
Arrays are a container for N elements of the same type. In cases where array
elements need to be addressed, a pointer to the array is created.

Assigning an array to another array will take N elements from the source
array and copy it over.
<<<<<<<


You can apply your same sayings to any variable:

>>>>>>
In general, an "int" variable effectively acts as a const pointer (in other
words: "int *const") the only exception being that sizeof... .

So you can think of "a = b;" as the attempt to modify "a" to make it point
to the same place as "b" is pointing to (because thats what pointer
assignment does). However, 'a' is const, so you can't modify it to point
anywhere else.

Of course, one could argue .... and make it instead assign the contents of
the int to the other int. I don't know, however, ... .
<<<<<<

Andrey Tarasevich

unread,
Aug 27, 2010, 1:53:19 PM8/27/10
to
Johannes Schaub (litb) wrote:
>> I don't think so, but I think it was intended.
>>
>> C++98 §5/8 says that an array is converted to pointer when it's used where
>> an rvalue is expected.
>>
>> Then §5.17/2 talks about the "value" of the right hand side of an
>> assignment.
>>
>
> Ohh i see now. So i guess it does the array-to-pointer conversion of the
> right side, and then tries to convert "T*" to "T[N]" but since there is no
> such implicit conversion, it fails hard. Thanks for the insights

Well, I would also expect this assignment to be "disabled" in C++ by a
different rule: array-to-pointer conversion on the RHS operand.

The 5/9 does indeed say that array-to-pointer conversion is applied when
an rvalue operand is expected.

Descriptions of various operators normally explicitly state whether a
given operand is expected/required to be an lvalue or an rvalue.
However, the description of the assignment operator only has the
requirements for the LHS operand. No requirement for the RHS is present
there.

So, where does it say that built-in assignment expects an rvalue on the
RHS??? I don't see it stated anywhere.

--
Best regards,
Andrey Tarasevich

Sprechen sie von C++

unread,
Aug 27, 2010, 6:40:05 PM8/27/10
to
"Johannes Schaub (litb)" <schaub-...@web.de> wrote in message
news:i58gdf$hpd$02$1...@news.t-online.com...

Use the STL as its there for reason.

#include <vector>

std::vector<int> a, b;
a[1] = 1;
a[2] = 2;

b = a;

will work as desired

Francesco S. Carta

unread,
Aug 27, 2010, 7:31:39 PM8/27/10
to

Apart that you missed the point, you posted non working code - that
happens to me too, but somebody always has to point it out, sorry.

Needs push_back() instead of subscript operators or else a properly
sized "a" before assigning the elements as you did. And main() to wrap
the code ;-)

--
FSC - http://userscripts.org/scripts/show/59948
http://fscode.altervista.org - http://sardinias.com

James Kanze

unread,
Aug 28, 2010, 5:48:57 PM8/28/10
to
On Aug 27, 5:17 pm, Juha Nieminen <nos...@thanks.invalid> wrote:
> Goran Pusic <gor...@cse-semaphore.com> wrote:
> > On Aug 27, 4:02 pm, "Johannes Schaub (litb)" <schaub-johan...@web.de>
> > wrote:
> >> I really can't find where the Standard forbids the following!

> >> int a[2] = { 1, 2 };
> >> int b[2];
> >> b = a;

> >> I thought somewhere the Standard says that lvalue
> >> expressions of array type are nonmodifiable, but I can't
> >> find it!

> > No idea about what standard might think, but if it did think
> > something, it would still sound like a silly arbitrary
> > constraint. What would be the rationale to prevent said
> > assignment?

There is none. Whether something is unmodifiable or not depends
on the object, not the lvalue expression used to modify it. And
arrays (at least non-const arrays) are certainly modifiable.

> It's not arbitrary at all, and there is a perfectly good
> rationale which can be derived from the definition of arrays.

> Arrays effectively act as const pointers (in other words "int*
> const"), the only exception being that the sizeof() operator
> returns the space taken by the entire array rather than the
> size of a pointer. (I know this is simplifying quite a lot,
> and there are probably other examples where they don't
> actually act like const pointers, but you get the idea.)

It's misleading, if not actually false. Arrays always act as
arrays. One characteristic of an array, however, is that it can
be implicitly converted into a pointer to the first element.
Not a const pointer, by the way, but since the result of the
conversion is an rvalue, there's no way of accessing the
resulting temporary in order to modify it.

The reason a = b is illegal if a is an array type is that
assignment to anything but a class type requires an rvalue on
the right hand side, and according to §5.2/8:

Whenever an lvalue expression appears as an operand of
an operator that expects an rvalue for that operand, the
lvalue-to-rvalue (4.1), array-to-pointer (4.2), or
function-to-pointer (4.3) standard conversions are
applied to convert the expression to an rvalue.

Thus, any array type to the right of a built-in assignment is
converted to a pointer. And there's no way to convert this
pointer back to the array type required by the left hand side.

Note that this is only true for built-in assignment. If the
left hand side is a class type with an assignment operator which
takes a reference, then an rvalue is not expected, none of the
conversions in the cited paragraph take place, and if the array
type can be used to initialize the reference, it will be.

> So you can think of "b = a;" as the attempt to modify 'b' to
> make it point to the same place as 'a' is pointing to (because
> that's what pointer assignment does). However, 'b' is const,
> so you can't modify it to point anywhere else.

IIRC, C did say something along those lines---that both the left
side and the right side of assignments underwent the array to
pointer conversion. And since the results of a conversion
(other than to a reference type in C++) is an rvalue, the
requirement that the left hand side be an lvalue was violated.
(But arrays still don't "effectively act like pointers". Even
in C, array types are very different from pointers, and there is
still only an implicit conversion.)

The C++ rules are slightly different, although the differences
generally can't be seen without the use of features not
available in C. The most obvious case:

struct Toto
{
Toto& operator=(int (&a)[5]);
};

Toto a;
int b[5];

a = b; // legal...

A somewhat more surprising one:

int (&f())[5];
/*
probably better written:
typedef int Array[5];
Array& f();
*/
int a[5];
a = f(); // legal! ?

To be frank, this one surprises me so much that I suspect that
there's still a constraint somewhere that I've missed. Perhaps
the combination of [§5.17/3] "If the left operand is not of
class type, the expression is implicitly converted (clause 4) to
the cv-unqualified type of the left operand" and/or [§5/6] "If
an expression initially has the type “reference to T” (8.3.2,
8.5.3), the type is adjusted to “T” prior to any further
analysis, the expression designates the object or function
denoted by the reference, and the expression is an lvalue" imply
that the "reference" in the type is stripped off before the
check for rvalue-ness is applied.

> Of course one could argue that the language should make an
> exception to this general principle in the case where you are
> assigning an array to another of the same type and size, and
> make it instead assign the contents of the array to the other
> array. I don't know, however, if the standardization committee
> had a reason to not impose such an exception to the general
> rule (and we are probably talking about the C standardization
> committee here, as this limitation is probably coming from C).

The C++ committee designed the rules to be compatible with
standard C. (Allowing array assignment would have been a simple
extension, but it wouldn't really have bought much unless they
also allows passing arrays to functions, which would have broken
compatibility completely.) The C committee designed their rules
to be compatible with all of the existing implementations, which
were based on the rules defined in K&R1. Which in turn derived
from B, which didn't have any types---everything was a "word",
and when you declared the dimensions of an array, the compiler
allocated an anonymous array, and put its address in the named
variable (which had type word).

--
James Kanze

James Kanze

unread,
Aug 28, 2010, 5:55:43 PM8/28/10
to

> > Any insights?

> In [dcl.array]

That's a note, so it's not normative. And it's obviously wrong,
since objects of array types certainly can be modified; the
programs I'm working on do it all the time.

See my response to Juha for a very formal description of what
the standard says. But it all boils down to the fact that an
array on the right hand side implicitly converts to a pointer,
and you can't assign a pointer to an array (C++), or a pointer
to the rvalue resulting from an array to pointer conversion (C,
*if* I'm remembering C correctly).

--
James Kanze

Goran Pusic

unread,
Aug 30, 2010, 6:06:23 AM8/30/10
to
On Aug 27, 6:17 pm, Juha Nieminen <nos...@thanks.invalid> wrote:
> Goran Pusic <gor...@cse-semaphore.com> wrote:
> > On Aug 27, 4:02 pm, "Johannes Schaub (litb)" <schaub-johan...@web.de>
> > wrote:
> >> I really can't find where the Standard forbids the following!
>
> >>   int a[2] = { 1, 2 };
> >>   int b[2];
> >>   b = a;
>
> >> I thought somewhere the Standard says that lvalue expressions of array type
> >> are nonmodifiable, but I can't find it!
>
> > No idea about what standard might think, but if it did think
> > something, it would still sound like a silly arbitrary constraint.
> > What would be the rationale to prevent said assignment?
>
>   It's not arbitrary at all, and there is a perfectly good rationale
> which can be derived from the definition of arrays.
>
>   Arrays effectively act as const pointers (in other words "int* const"),
> the only exception being that the sizeof() operator returns the space
> taken by the entire array rather than the size of a pointer. (I know this
> is simplifying quite a lot, and there are probably other examples where
> they don't actually act like const pointers, but you get the idea.)

Well, they act as such but AFAIK, aren't it. Ah, I see it's all
explained already. Never mind then.

Goran.

0 new messages