Topic: interpretation of the expression new (int*)[10]


Author: kanze@gabi-soft.de (James Kanze)
Date: Fri, 1 Mar 2002 18:31:33 GMT
Raw View
Moritz Franosch <jfranosc@physik.tu-muenchen.de> wrote in message
news:<rxx1yf669tb.fsf@synapse.t30.physik.tu-muenchen.de>...
> Please consider the following C++ program

> int main() {
>   int** p;
>   p=new int*[10];     // 1
>   p=new (int*)[10];   // 2
>   p=(new (int*))[10]; // 3
> }

> According to the C++ standard, are 1 and 2 equivalent or 2 and 3?

2 and 3 are equivalent.

> In my interpretation of the standard, 1 means new returns a pointer
> to an array of 10 integers,

1 allocates 10 pointers to int, and returns a pointer to the first,
thus, an int**.  Perfectly legal.

> 2 is equivalent to 3 and 3 means
> p=(new (int*))+10.

Not quite.  The sequence "(int*)[10]", isn't a legal type name, so the
new expression in 2 is "new (int*)" -- which is the equivalent to the
new expression in 3.  In both cases, a single int* is allocated, and
it's address is returned.  In both cases, the [10] then adds 10 to the
returned pointer, and dereferences it -- undefined behavior, but since
the result of dereferencing an int** is an int*, the compiler should
complain about a type mismatch.

> GCC version 3.0.2 sees 1 and 2 as equivalent, which is wrong. Intel
> C++ version 5.0.1 is standard compliant.

    [...]

> I can't see a way to get '(int*)' for a type-specifier-seq, so 'new
> (int*)[10]' is no new-expression, but 'new (int*)' is and therefore
> 'new (int*)[10]' (2) must be interpreted as '(new (int*))[10]' (3).

Exactly.  You just got the types a bit mixed up.

> Is my interpretation of the standard right? If so, I'll send a bug
> report to the GCC team.

Do so.

--
James Kanze                                   mailto:kanze@gabi-soft.de
Beratung in objektorientierer Datenverarbeitung --
                             -- Conseils en informatique orient   e objet
Ziegelh   ttenweg 17a, 60598 Frankfurt, Germany, T   l.: +49 (0)69 19 86 27

---
[ 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.research.att.com/~austern/csc/faq.html                ]





Author: Moritz Franosch <jfranosc@physik.tu-muenchen.de>
Date: Wed, 27 Feb 2002 14:39:09 CST
Raw View
Please consider the following C++ program

int main() {
  int** p;
  p=new int*[10];     // 1
  p=new (int*)[10];   // 2
  p=(new (int*))[10]; // 3
}

According to the C++ standard, are 1 and 2 equivalent or 2 and 3?

In my interpretation of the standard, 1 means new returns a pointer to
an array of 10 integers, 2 is equivalent to 3 and 3 means
p=(new (int*))+10.

GCC version 3.0.2 sees 1 and 2 as equivalent, which is wrong. Intel
C++ version 5.0.1 is standard compliant.

In the following, I try to proof that 2 is not equivalent to 1
according to my "November 1997 Draft C++ Standard".

A new-expression is

  new-expression:
             ::opt new new-placementopt new-type-id new-initializeropt
             ::opt new new-placementopt ( type-id ) new-initializeropt

For the moment let's take the second rule, so we get

new ( type-id ) new-initializer

But a new-initializer

new-initializer:
             ( expression-listopt )

must start with '(', thus we cannot get 'new (int*)[10]' as a
new-expression in this way.


It remains to substitute new-expression by

new new-type-id


    new-type-id:
             type-specifier-seq new-declaratoropt
    new-declarator:
             ptr-operator new-declaratoropt
             direct-new-declarator
    direct-new-declarator:
             [ expression ]
             direct-new-declarator [ constant-expression ]

We continue with

new type-specifier-seq new-declarator

new type-specifier-seq ptr-operator direct-new-declarator
or
new type-specifier-seq direct-new-declarator

new type-specifier-seq *[10]
or
new type-specifier-seq [10]


     type-specifier-seq:
             type-specifier type-specifier-seqopt
     type-specifier:
             simple-type-specifier
             class-specifier
             enum-specifier
             elaborated-type-specifier
             cv-qualifier
     simple-type-specifier:
             ::opt nested-name-specifieropt type-name
             ::opt nested-name-specifier template template-id
             char
             wchar_t
             bool
             short
             int
             long
             signed
             unsigned
             float
             double
             void
     elaborated-type-specifier:
             class-key ::opt nested-name-specifieropt identifier
             enum ::opt nested-name-specifieropt identifier
             typename ::opt  nested-name-specifier identifier
             typename ::opt  nested-name-specifier templateopt template-id


I can't see a way to get '(int*)' for a type-specifier-seq, so 'new
(int*)[10]' is no new-expression, but 'new (int*)' is and therefore
'new (int*)[10]' (2) must be interpreted as '(new (int*))[10]' (3).


Is my interpretation of the standard right? If so, I'll send a bug
report to the GCC team.


Thank you for your help,

Moritz

---
[ 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.research.att.com/~austern/csc/faq.html                ]





Author: Michael Spencer <michael_spencer@btclick.com>
Date: Thu, 28 Feb 2002 02:21:46 GMT
Raw View
Moritz Franosch wrote:
>
> Please consider the following C++ program
>
> int main() {
>   int** p;
>   p=new int*[10];     // 1
>   p=new (int*)[10];   // 2
>   p=(new (int*))[10]; // 3
> }
>
> According to the C++ standard, are 1 and 2 equivalent or 2 and 3?
>
> In my interpretation of the standard, 1 means new returns a pointer to
> an array of 10 integers, 2 is equivalent to 3 and 3 means
> p=(new (int*))+10.
>

In 1, new allocates an array of 10 pointer to ints, so the return type
is int **.  3 is equivalent to p=*(new (int*) + 10), so you're
assigning an int * to an int **.

Not sure how 2 compiles.  I see it as a syntax error.  If it's an
array access (like 3), then new (int*) must be a postfix expression:

  postfix-expression -> postfix-expression [ expression ]

But I don't see how postfix-expression derives new-expression:

  postfix-expression -> ... -> new-expression

Mike

> Thank you for your help,
>
> Moritz
>
> ---
> [ 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.research.att.com/~austern/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.research.att.com/~austern/csc/faq.html                ]





Author: Moritz Franosch <jfranosc@physik.tu-muenchen.de>
Date: Thu, 28 Feb 2002 16:11:39 GMT
Raw View
Michael Spencer <michael_spencer@btclick.com> writes:

> Moritz Franosch wrote:
> >
> > Please consider the following C++ program
> >
> > int main() {
> >   int** p;
> >   p=new int*[10];     // 1
> >   p=new (int*)[10];   // 2
> >   p=(new (int*))[10]; // 3
> > }
> >
> > According to the C++ standard, are 1 and 2 equivalent or 2 and 3?
>
> In 1, new allocates an array of 10 pointer to ints, so the return type
> is int **.  3 is equivalent to p=*(new (int*) + 10), so you're
> assigning an int * to an int **.

Yes, your version is right of course. GCC 3.0.2 only warns in case 3
that an int * is assigned to an int **, Intel 5.0.1 gives the same
warning in cases 2 and 3.

> Not sure how 2 compiles.  I see it as a syntax error.

Then both compilers would be wrong, could well be.

> If it's an array access (like 3), then new (int*) must be a postfix
> expression:
>
>   postfix-expression -> postfix-expression [ expression ]
>
> But I don't see how postfix-expression derives new-expression:
>
>   postfix-expression -> ... -> new-expression

Difficult to show that it is not possible. But I see your
point. Because of

 postfix-expression:
             primary-expression
             postfix-expression [ expression ]
             ...

we probably need

primary-expression [10]

and have to get from primary-expression to a new-expression, but

 primary-expression:
             literal
             this
             ( expression )
             id-expression

and so we have to use the parentheses '( expression )'.


Thank you for your additional insight,

Moritz

---
[ 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.research.att.com/~austern/csc/faq.html                ]