new an array of pointers

V

Victor Bazarov


There undoubtedly is. Did you try reading the error messages carefully?
What did they say? What's unclear about them?

V
 
J

James Kanze


Evaluates as:

int** p = new (int (*([30]));

An array of 30 int*.
int **p = new (int) *[30]; //ERROR

int** p = (new (int)) * [30];

Don't know what the compiler is supposed to make of the [30],
given that there's no address expression to the left of it.
(And the '*' is multiplication.)
int **p = new (int*)[30]; //ERROR

int** p = (new (int*))[30];

Here, the initialization expression is a syntactically legal
expression (but would have undefined behavior at runtime), but
it doesn't have the type int**: the new expression returns an
int** (pointing to a single uninitialized int*), but
dereferencing it (remember, a is the same as *(a+b)) results
in an int*.
----------
Any difference between them?

They mean different things.
 
A

Alf P. Steinbach

* James Kanze:

Evaluates as:

int** p = new (int (*([30]));

An array of 30 int*.
int **p = new (int) *[30]; //ERROR

int** p = (new (int)) * [30];

Don't know what the compiler is supposed to make of the [30],
given that there's no address expression to the left of it.
(And the '*' is multiplication.)
int **p = new (int*)[30]; //ERROR

int** p = (new (int*))[30];

Here, the initialization expression is a syntactically legal
expression (but would have undefined behavior at runtime),

new expressions are a wilderness of special case rules. On reading your
statement I thought huh, that must a placement form syntactically. But as it
turned out[1] I was wrong[2] about why you're wrong here,


<example>
"ComeauTest.c", line 3: error: this operator is not allowed at this point; use
parentheses
int **p = new (int*)[30];
^

"ComeauTest.c", line 3: error: a value of type "int *" cannot be used to initialize
an entity of type "int **"
int **p = new (int*)[30];
but
it doesn't have the type int**: the new expression returns an
int** (pointing to a single uninitialized int*), but
dereferencing it (remember, a is the same as *(a+b)) results
in an int*.


Right, but first it must pass muster syntactically.


Cheers,

- Alf

Notes:
[1] Also g++ and MSVC object to the construct; g++ like Comeau.
[2] Yet another case where coffee is called for.
 
T

thomas

I ask this question because I thought "int *" is just like a type like
"int" and

------
int **p = new int* [30];
-----

just like

----
int *p = new int [30];
----

I thought it is obvious and natural until problem occurs.

I tried the expression
-----

int main(){
int **p = new (int (*([30])));
}
-----
and got error message again in VC2005
----
1>------ Build started: Project: test, Configuration: Debug Win32
------
1>Compiling...
1>test.cpp
1>e:\lab\test\test\test.cpp(3) : error C3409: empty attribute block is
not allowed
1>e:\lab\test\test\test.cpp(3) : error C2143: syntax error : missing
']' before 'constant'
1>e:\lab\test\test\test.cpp(3) : error C2059: syntax error :
'constant'
1>e:\lab\test\test\test.cpp(3) : error C2059: syntax error : ')'
1>Build log was saved at "file://e:\Lab\test\test\Debug\BuildLog.htm"
1>test - 4 error(s), 0 warning(s)
========== Build: 0 succeeded, 1 failed, 0 up-to-date, 0 skipped
==========
 
J

James Kanze

* James Kanze:
Evaluates as:
int** p = new (int (*([30]));
An array of 30 int*.
int **p = new (int) *[30]; //ERROR
int** p = (new (int)) * [30];
Don't know what the compiler is supposed to make of the [30],
given that there's no address expression to the left of it.
(And the '*' is multiplication.)
int **p = new (int*)[30]; //ERROR
int** p = (new (int*))[30];
Here, the initialization expression is a syntactically legal
expression (but would have undefined behavior at runtime),
new expressions are a wilderness of special case rules.

They do have their own particular grammar. The goal, of course,
is to allow the compiler to know where the type ends, and the
initialization expression begins. The result is that while the
compiler now knows, the human reader often has problems.
On reading your statement I thought huh, that must a placement
form syntactically.

No, but I'll bet it would be possible to construct some cases
where that sort of ambiguity would exist.
But as it turned out[1] I was wrong[2] about why you're wrong
here,
<example>
"ComeauTest.c", line 3: error: this operator is not allowed at this point; use
parentheses
int **p = new (int*)[30];
^
"ComeauTest.c", line 3: error: a value of type "int *" cannot be used to initialize
an entity of type "int **"
int **p = new (int*)[30];
</example>
but
it doesn't have the type int**: the new expression returns an
int** (pointing to a single uninitialized int*), but
dereferencing it (remember, a is the same as *(a+b)) results
in an int*.

Right, but first it must pass muster syntactically.

It does. At least according to my copy of the epxression. The
new expression is "new (int*)". And that gets used as the left
operand of the [] expression. I don't know what Comeau is
complaining about with "this operator is not allowed at this
point---the grammar clearly allows it. (The new expression, in
this case, matches "::[opt] new new-placement[opt] ( type-id )
new-initializer[opt]", with none of the optional parts present.
 
J

James Kanze

I ask this question because I thought "int *" is just like a type like
"int" and

It is. But note that there are two syntaxes for new
expressions:
new new-type-id
and
new ( type-id )
(both simplified by eliminating the optional bits). And a
new-type-id only accepts a small subset of legal type
expressions; for anything more general, you need the second
form.
just like

Those two are fine. Basically, a new-type-id is one or more
type-specifiers (things like int, const or names of classes),
followed by zero or more ptr-operator (a *), followed by zero or
more direct-new-declaration ([x], with the requirement that in
all but the first, the x must be a constant). For anything
else, you need the second form, with parentheses.
I thought it is obvious and natural until problem occurs.
I tried the expression
-----
int main(){
int **p = new (int (*([30])));}
-----
and got error message again in VC2005
----
1>------ Build started: Project: test, Configuration: Debug Win32
------
1>Compiling...
1>test.cpp
1>e:\lab\test\test\test.cpp(3) : error C3409: empty attribute block is
not allowed
1>e:\lab\test\test\test.cpp(3) : error C2143: syntax error : missing
']' before 'constant'
1>e:\lab\test\test\test.cpp(3) : error C2059: syntax error :
'constant'
1>e:\lab\test\test\test.cpp(3) : error C2059: syntax error : ')'
1>Build log was saved at "file://e:\Lab\test\test\Debug\BuildLog.htm"
1>test - 4 error(s), 0 warning(s)
========== Build: 0 succeeded, 1 failed, 0 up-to-date, 0 skipped
==========
----
So I think more clarification may be required.

Compiler error? At first view, your code looks correct, and
both g++ and Sun CC accept it.
 
J

Johannes Schaub (litb)

James said:
But as it turned out[1] I was wrong[2] about why you're wrong
here,
<example>
"ComeauTest.c", line 3: error: this operator is not allowed at this
point; use
parentheses
int **p = new (int*)[30];
^
"ComeauTest.c", line 3: error: a value of type "int *" cannot be used to
initialize
an entity of type "int **"
int **p = new (int*)[30];
</example>
but
it doesn't have the type int**: the new expression returns an
int** (pointing to a single uninitialized int*), but
dereferencing it (remember, a is the same as *(a+b)) results
in an int*.

Right, but first it must pass muster syntactically.

It does. At least according to my copy of the epxression. The
new expression is "new (int*)". And that gets used as the left
operand of the [] expression. I don't know what Comeau is
complaining about with "this operator is not allowed at this
point---the grammar clearly allows it. (The new expression, in
this case, matches "::[opt] new new-placement[opt] ( type-id )
new-initializer[opt]", with none of the optional parts present.


First, i want to agree that new expressions are a wilderness of special
rules xD

I think the problem with "new (int*)[30]" is that "new (int*)" is not a
postfix-expression. new-expression is branching off unary-expression, so if
you want a new-expression on the left of op[], you need parens.

However, think that comeau is wrong at another place on parsing new-
expressions, when it accepts "new (int[n]);" and "new (int[0, 1]);" when n
is a runtime value. "type-id" won't accept any of these. I'm interested to
see what they do in C++0x when they need to check this in SFINAE contexts.
 
J

James Kanze

James said:
"ComeauTest.c", line 3: error: a value of type "int *" cannot be used to
initialize
an entity of type "int **"
int **p = new (int*)[30];
</example>
but it doesn't have the type int**: the new expression
returns an int** (pointing to a single uninitialized
int*), but dereferencing it (remember, a is the same
as *(a+b)) results in an int*.
Right, but first it must pass muster syntactically.

It does. At least according to my copy of the epxression.
The new expression is "new (int*)". And that gets used as
the left operand of the [] expression. I don't know what
Comeau is complaining about with "this operator is not
allowed at this point---the grammar clearly allows it. (The
new expression, in this case, matches "::[opt] new
new-placement[opt] ( type-id ) new-initializer[opt]", with
none of the optional parts present.

First, i want to agree that new expressions are a wilderness
of special rules xD
I think the problem with "new (int*)[30]" is that "new (int*)"
is not a postfix-expression. new-expression is branching off
unary-expression, so if you want a new-expression on the left
of op[], you need parens.

Good point. I hadn't considered that side of things, but you
(and Comeau) are right: the grammar for [] is
"postfix-expression [ expression ]", and a new expression is not
a postfix-expression.
However, think that comeau is wrong at another place on
parsing new- expressions, when it accepts "new (int[n]);" and
"new (int[0, 1]);" when n is a runtime value. "type-id" won't
accept any of these. I'm interested to see what they do in
C++0x when they need to check this in SFINAE contexts.

That's an interesting point. It is obviously (I think)
desirable that "new (int[n])" work, so that I can also write
things like "new (int(*)()[n])" to allocate an array of pointers
to functions. But the grammar does seem to forbid it (although
it allows "new (int[])" or even "new (int[5][])"-- hopefully
there are semantic constraints which forbid this).

I wonder if a DR is in order.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
474,148
Messages
2,570,838
Members
47,385
Latest member
Joneswilliam01

Latest Threads

Top