mhyman@hsfmsh.uucp (Marco S. Hyman) (03/08/90)
A co-worker came up with a problem that brings up an interesting C++ question. He wanted to create a pointer to an array of void pointers. The definition he used was: void * (*a)[]; In the constructor of the class `a' was defined in he tried to allocate memory using a = new (void *)[size]; // size was passed to the constructor Cfront complained with the error: error: bad assignment type: void *(*)[] = void * When the problem came to me I first tried some things to see if I could get memory allocated for `a' as defined. Things tried were a = new void *(*)[size]; error: syntax error a = new (void *(*)[size]); error: bad assignment type: void *(*)[] = void *(**)[size] a = new void **[size]; error: bad assignment type: void *(*)[] = void **[size] After several tries I came up with something cfront liked a = new (void *(*)[])[size]; The problem is that the code generated was not what was expected. Memory was allocated for one void pointer; size was not part of the allocation equation. The generated code looked like (cleaned up for easier reading): this->a = (((char *(**)[]) __nw__FUi(sizeof(char *(*)[]))))[size]; The solution was, of course, to get the [] out of the definition and use void ***a; a = new void **[size]; What is void * (*)[] then? Is there a way to allocate memory for it using new? // marc
mhyman@hsfmsh.uucp (Marco S. Hyman) (03/09/90)
There are some differences between Zortech and cfront in the use of new
with array definitions. This, from a co-worker [[with my comments like
this]], shows the differences. Which is right?
----------------------------
I saw your message on USENET. Something didn't seem exactly the same
as what I did, so I ran your examples through the Zortech compiler.
As I suspected, the results I got were different (but not substantially,
except in first case) from those with CFront:
// Base class definition -- doesn't change.
class F
{
void * (*a)[];
public:
F( int size );
};
First constructor compiles, but generates the wrong code. Allocates one
void *, then tries to dereference with [size]. Odd that Cfront didn't like
this one at all:
F::F( int size )
{
a = new (void *)[size]; // case 1
}
Second constructor doesn't compile:
F::F( int size )
{
a = new void *(*)[size]; // case 2
^
"test2.cpp", line 13 Syntax error: expression expected
}
Third doesn't compile:
F::F( int size )
{
a = new (void *(*)[size]); // case 3
^
"test3.cpp", line 13 Syntax error: integer constant expression expected
}
Forth constructor. This works! Without changing the base definition
of the array a! I think it is because a[] and (*a)[] are considered
identical to C. (consider that an array is known by the pointer to its
first element!)
F::F( int size )
{
a = new void **[size]; // case 4
}
[[This does not work with cfront unless the definition of a is changed to
void ***a; cfront give a type match error]]
Fifth constructor. Compiles, but generates the same code as case 1.
F::F( int size )
{
a = new (void *(*)[])[size]; // case 5
}
There were other variations I tried in a vain attempt to get this
business to work, but I can't remember them all. Suffice it to say
that the designers of C++ sure made the good old process of
a = malloc( size * sizeof(void *) ) and made it much too obfuscated
in an attempt to make it type-safe.
You can post this, if you like.
Bill Coleman
-------------------------------------
If you'd like to respond to Bill use one of the following addresses.
hsfmsh!bcoleman-vax@sfsun.west.sun.com
...!hoptoad!hsfmsh!bcoleman-vax
// marc