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