[lnkForumImage]
TotalShareware - Download Free Software

Confronta i prezzi di migliaia di prodotti.
Asp Forum
 Home | Login | Register | Search 


 

Forums >

comp.lang.c++

stupid void**

Chris Becke

11/12/2008 9:22:00 AM

In C and in older C++ compilers, you could write code like this

void a(void** pp); // declare a function that takes a pointer to a pointer-to-void.
struct I {}; // some struct.
I *i1,**i2; // some kinds of i.

a(&i1); // this works
a(i2); // this also worked.
a(i1); // error: incorrect levels of indirection
a(&i2); // error: incorrect levels of indirection

Now, c++ compilers just don't like void* anymore. meaning we absolutely have to static cast to a void** because c++ compiler are too damn high and mighty to let a void** slip past on a mere levels of indirection check.

a((void**)&i1); // this works
a((void**)i2); // this also worked.
a((void**)i1); // oops
a((void**)&i2); // oops

Yay for c++ helping us avoid bugs.
indirection checking was useful damnit.
10 Answers

Andrey Tarasevich

11/12/2008 2:55:00 PM

0

Chris Becke wrote:
> In C and in older C++ compilers, you could write code like this
>
> void a(void** pp); // declare a function that takes a pointer to a pointer-to-void.
> struct I {}; // some struct.
> I *i1,**i2; // some kinds of i.
>
> a(&i1); // this works
> a(i2); // this also worked.
> a(i1); // error: incorrect levels of indirection
> a(&i2); // error: incorrect levels of indirection

No, you couldn't. Neither in C nor in C++. None of these ever "worked".
Apparently, you've been using some silly old broken compiler and a bunch
of your own hacks, and for some reason mistook that compiler's silly
quirks for C and/or C++ language features.

> Now, c++ compilers just don't like void* anymore. meaning we absolutely
> have to static cast to a void** because c++ compiler are too damn high
> and mighty to let a void** slip past on a mere levels of
> indirection check.

Huh? You seemed to be talking about 'void**'. And here you suddenly
mention 'void*', which has very little to do with 'void**'.

BTW, "static cast to void**"? The casts in question cannot be performed
by 'static_cast'. If your compiler allows it, it probably means that you
are continuing to stick with some rather silly compiler.

> a((void**)&i1); // this works
> a((void**)i2); // this also worked.
> a((void**)i1); // oops
> a((void**)&i2); // oops
>
> Yay for c++ helping us avoid bugs.
> indirection checking was useful damnit.

All these four calls are "bugs", just like the original four calls were.
The are "bugs" in a sense that that the resultant pointer cannot be
immediately used as a 'void**' pointer anyway. The compiler you are
using now looks better because it refuses to compile the useless
original code. This should have been something to make you think about
what you are doing. Instead, you decided to slap a cast on it to sweep
the error under the carpet. Well, no wonder all you get from it is a
bunch of "oops"!

--
Best regards,
Andrey Tarasevich

blargg.h4g

11/12/2008 6:38:00 PM

0

Chris Becke wrote:

> In C and in older C++ compilers, you could write code like this
>
> void a(void** pp); // declare a function that takes a pointer to a
> pointer-to-void.
> struct I {}; // some struct.
> I *i1,**i2; // some kinds of i.
>
> a(&i1); // this works
> a(i2); // this also worked.
> a(i1); // error: incorrect levels of indirection
> a(&i2); // error: incorrect levels of indirection
>
> Now, c++ compilers just don't like void* anymore. meaning we absolutely
> have to static cast to a void** because c++ compiler are too damn high
> and mighty to let a void** slip past on a mere levels of indirection
> check.
>
> a((void**)&i1); // this works
> a((void**)i2); // this also worked.
> a((void**)i1); // oops
> a((void**)&i2); // oops
>
> Yay for c++ helping us avoid bugs.

Yes, indeed, disallowing it eliminates bugs. If T** implicitly converted
to void**, you could do

int* p;
void** pp = &p; // error, but you're arguing that this be allowed
char c;
*pp = &c; // if allowed, would be equivalent to
// reinterpret_cast<void*&> (p) = &c
*p = 1234; // oops, p points to a char

without any casting. Also, if the standard required a compiler to allow
this, it would have to use the same representation for all pointer types,
rather than as currently where it can use fewer bits for pointers to types
with alignment requirements more strict than char's.

Old Wolf

11/13/2008 12:15:00 AM

0

On Nov 12, 10:21 pm, "Chris Becke" <chris.be...@gmail.com> wrote:
> In C and in older C++ compilers, you could write code like this
>
>   void a(void** pp); // declare a function that takes a pointer to a pointer-to-void.
>   struct I {}; // some struct.
>   I *i1,**i2; // some kinds of i.
>
>   a(&i1);  // this works
>   a(i2);     // this also worked.
>   a(i1);     // error: incorrect levels of indirection
>   a(&i2);  // error: incorrect levels of indirection

Just backing up what Andrey said; none of these ever
worked in any standard version of C or C++. A void**
can only point to exactly a void* , not anything else.

Chris Becke

11/13/2008 8:18:00 AM

0

"blargg" <blargg.h4g@gishpuppy.com> wrote in message news:blargg.h4g-1211081238250001@192.168.1.4...
> Chris Becke wrote:
> without any casting. Also, if the standard required a compiler to allow
> this, it would have to use the same representation for all pointer types,
> rather than as currently where it can use fewer bits for pointers to types
> with alignment requirements more strict than char's.

C99 still allows transformation to AND from void*

void* x;
int* y;
x=y; // both are legal in C99. At least the latest versions of MSVC and GCC compile this fragment.
y=x;

That aside, I do get the problem with pointer representations.

But, it seems a bit subversive to have a universal pointer type, and then disallow it being used as a universal pointer type. In its current form in c++, void* should have just been thrown out. It saves us a typecast only when casting to, not from void*s, and c++ hasn't introduced any kind of indirection counting typecast, making void* worse than dangerous. All because some overly zelous individual decided that void** needs to be treated as a special case, definately note a pointer to a thing that is a void*.


James Kanze

11/13/2008 9:55:00 AM

0

On Nov 13, 9:18 am, "Chris Becke" <chris.be...@gmail.com> wrote:
> "blargg" <blargg....@gishpuppy.com> wrote in
> messagenews:blargg.h4g-1211081238250001@192.168.1.4...
> > Chris Becke wrote:
> > without any casting. Also, if the standard required a
> > compiler to allow this, it would have to use the same
> > representation for all pointer types, rather than as
> > currently where it can use fewer bits for pointers to types
> > with alignment requirements more strict than char's.

> C99 still allows transformation to AND from void*

> void* x;
> int* y;
> x=y; // both are legal in C99. At least the latest versions of MSVC and GCC compile this fragment.
> y=x;

As does C++. The only difference is that C++ requires a
static_cast for the conversion from void*.

> That aside, I do get the problem with pointer representations.

> But, it seems a bit subversive to have a universal pointer
> type, and then disallow it being used as a universal pointer
> type.

The universal pointer type is void*, not void**.

> In its current form in c++, void* should have just been thrown
> out. It saves us a typecast only when casting to, not from
> void*s,

Which is probably a mistake---it should probably require the
conversion to be explicit in both directions.

> and c++ hasn't introduced any kind of indirection
> counting typecast, making void* worse than dangerous.

I'm not sure that I follow you here. C++ didn't change the
meaning of void* from that of C.

> All because some overly zelous individual decided that void**
> needs to be treated as a special case, definately note a
> pointer to a thing that is a void*.

What? void** (unlike void*) isn't a special case at all; it's a
pointer to a void*, and only to a void*. If I understand your
initial code, you wanted it to point to an int*.

And I don't know who you mean by "some overly zealous
individual". It's been that way in both C and C++ ever since
there was void.

--
James Kanze (GABI Software) email:james.kanze@gmail.com
Conseils en informatique orientée objet/
Beratung in objektorientierter Datenverarbeitung
9 place Sémard, 78210 St.-Cyr-l'École, France, +33 (0)1 30 23 00 34

James Kanze

11/13/2008 9:57:00 AM

0

On Nov 13, 1:15 am, Old Wolf <oldw...@inspire.net.nz> wrote:
> On Nov 12, 10:21 pm, "Chris Becke" <chris.be...@gmail.com> wrote:

> > In C and in older C++ compilers, you could write code like this

> > void a(void** pp); // declare a function that takes a pointer to a pointer-to-void.
> > struct I {}; // some struct.
> > I *i1,**i2; // some kinds of i.
>
> > a(&i1); // this works
> > a(i2); // this also worked.
> > a(i1); // error: incorrect levels of indirection
> > a(&i2); // error: incorrect levels of indirection

> Just backing up what Andrey said; none of these ever
> worked in any standard version of C or C++. A void**
> can only point to exactly a void* , not anything else.

You can drop the standard---they've never worked in any version
of C or C++. (Some very, very early versions of C did allow
implicit conversions between any pointer types. Even then,
however, this was documented as and "unintentional"
feature---that the language itself required an explicit
conversion. And of course, this was long before there was a
keyword void.)

--
James Kanze (GABI Software) email:james.kanze@gmail.com
Conseils en informatique orientée objet/
Beratung in objektorientierter Datenverarbeitung
9 place Sémard, 78210 St.-Cyr-l'École, France, +33 (0)1 30 23 00 34

Andrey Tarasevich

11/13/2008 2:42:00 PM

0

Chris Becke wrote:
>
> C99 still allows transformation to AND from void*
>
> void* x;
> int* y;
> x=y; // both are legal in C99. At least the latest versions of MSVC and GCC compile this fragment.
> y=x;
>
> That aside, I do get the problem with pointer representations.
>
> But, it seems a bit subversive to have a universal pointer type, and then
> disallow it being used as a universal pointer type. In its current
> form in c++, void* should have just been thrown out.

This is all great, but it is about 'void*', while your original message
was about 'void**', which is a completely different thing.

> It saves us a typecast only when casting to, not from void*s, and c++
> hasn't introduced any kind of indirection counting typecast,

C doesn't have any "indirection counting typecasts" either. If you saw
something like that in the past, it probably was a fancy feature of some
specific compiler.

> making void* worse than dangerous.

'void*'??? No.

> All because some overly zelous individual decided that void** needs to
> be treated as a special case, definately note a pointer to a thing
> that is a void*.

No, you got it completely upside down. 'void**' is not treated as a
special case. The contrary is true: 'void**' is treated as a general
case. 'int**' cannot converted to 'void**' for precisely the same
reasons why, say, 'int*' cannot be converted to 'double*' (despite the
valid 'int' -> 'double' conversion).

--
Best regards,
Andrey Tarasevich

Rolf Magnus

11/13/2008 6:28:00 PM

0

Chris Becke wrote:

> "blargg" <blargg.h4g@gishpuppy.com> wrote in message
> news:blargg.h4g-1211081238250001@192.168.1.4...
>> Chris Becke wrote:
>> without any casting. Also, if the standard required a compiler to allow
>> this, it would have to use the same representation for all pointer types,
>> rather than as currently where it can use fewer bits for pointers to
>> types with alignment requirements more strict than char's.
>
> C99 still allows transformation to AND from void*

Yes. but a pointer to void is not the same as a pointer to a pointer.

> But, it seems a bit subversive to have a universal pointer type, and then
> disallow it being used as a universal pointer type.

It's not. For any pointer, the standard requires that its value can be
converted to void* and back without loss. What it doesn't say is that such a
pointer can be converted into a pointer to pointer and back without loss.

> It saves us a typecast only when casting to, not from void*s, and c++
> hasn't introduced any kind of indirection counting typecast, making void*
> worse than dangerous.

A void** isn't just a void pointer with one additional level of indirection
or something like that. It's a different pointer type.

> All because some overly zelous individual decided that void** needs to be
> treated as a special case, definately note a pointer to a thing that is a
> void*.

There is no special case. void** is just handle the same as pointers to any
other pointer type.

Pete Becker

11/13/2008 6:52:00 PM

0

On 2008-11-13 13:28:17 -0500, Rolf Magnus <ramagnus@t-online.de> said:

>
> A void** isn't just a void pointer with one additional level of indirection
> or something like that. It's a different pointer type.

And it can be implicitly converted to void*, just like any other pointer type.

--
Pete
Roundhouse Consulting, Ltd. (www.versatilecoding.com) Author of "The
Standard C++ Library Extensions: a Tutorial and Reference
(www.petebecker.com/tr1book)

Old Wolf

11/15/2008 4:08:00 AM

0

On Nov 13, 10:57 pm, James Kanze <james.ka...@gmail.com> wrote:
> On Nov 13, 1:15 am, Old Wolf <oldw...@inspire.net.nz> wrote:
> > Just backing up what Andrey said; none of these ever
> > worked in any standard version of C or C++. A void**
> > can only point to exactly a void* , not anything else.
>
> You can drop the standard---they've never worked in any version
> of C or C++.

I'm generally cautious about saying "any version
of C" -- there have been a lot of weird compiler
extensions and bugs over the years!