[comp.lang.c] Operations on pointers to void.

john@basho.uucp (John Lacey) (08/10/90)

What operations are legal on pointers to void?  K&R2 is it's usual self
on the matter---no one can tell if what they say is possible, required, 
complete, a couple of examples, or what.  Harbison and Steele are their 
much more explicit selves, but still, all they say is that void *'s can
be assigned to or from without casts, and that dereferencing and 
subscripting are illegal.

But, what about pointer arithmetic?  And it that is legal, what size object
does a void * point to?  If there was justice in the world, I suppose that
it should be legal, and that a void * points to an object of size 0, but
gcc thinks the size is 1 (and gives no complaints about the following code
compiled with -ansi -pedantic -Wall:

#include <stdio.h>

int
main()
{
char foo [] = "This is a test string.";
void * a = foo;
void * b = &foo[1];

printf ( "%s\n", (++a == b) ? "Object size is 1" : "Object size is NOT 1" );
return ( 0 );
}

and further, gives the aforementioned result of "Object size is 1").

Ah what gives?
-- 
John Lacey, 
   E-mail:  ...!osu-cis!n8emr!uncle!basho!john  (coming soon: john@basho.uucp)
   V-mail:  (614) 436--3773, or 487--8570
"What was the name of the dog on Rin-tin-tin?"  --Mickey Rivers, ex-Yankee CF

steve@taumet.com (Stephen Clamage) (08/10/90)

john@basho.uucp (John Lacey) writes:

>What operations are legal on pointers to void?  ...

You may cast to or from type void*.
You may assign, initialize, or pass as a parameter any pointer to an object
of type void*, and vice versa.
You may not dereference an object of type void*.

>But, what about pointer arithmetic?  And it that is legal, what size object
>does a void * point to?

You cannot do pointer arithmetic with an object of void*.  No object may
have type void, so no size can be associated with it.  It is helpful
to think of void as "not anything", rather than "zero".  Void* is a
special case, and you can think of it as "pointing to something unspecified".
-- 

Steve Clamage, TauMetric Corp, steve@taumet.com

henry@zoo.toronto.edu (Henry Spencer) (08/10/90)

In article <1990Aug9.231614.5196@basho.uucp> john@basho.uucp (John Lacey) writes:
>... dereferencing and subscripting are illegal.
>But, what about pointer arithmetic? ...

Subscripting *is* pointer arithmetic.  Apart from passing them around and
comparing them to each other and to NULL, there is *nothing* you can do
with `void *'s except convert them to another kind of pointer.  No
dereferencing, no arithmetic.  They are containers for other kinds of
pointers, not pointers themselves.

Many compilers, especially old ones with `void *' hastily kludged in,
treat `void *' much like `char *'.  That is a compiler bug.
-- 
It is not possible to both understand  | Henry Spencer at U of Toronto Zoology
and appreciate Intel CPUs. -D.Wolfskill|  henry@zoo.toronto.edu   utzoo!henry

colin@array.UUCP (Colin Plumb) (08/11/90)

In article <1990Aug10.165644.9238@zoo.toronto.edu> henry@zoo.toronto.edu (Henry Spencer) writes:
> Subscripting *is* pointer arithmetic.  Apart from passing them around and
> comparing them to each other and to NULL, there is *nothing* you can do
> with `void *'s except convert them to another kind of pointer.  No
> dereferencing, no arithmetic.  They are containers for other kinds of
> pointers, not pointers themselves.

Exactly.  A void * can be assigned, passed, returned, and compared.  Period.

> Many compilers, especially old ones with `void *' hastily kludged in,
> treat `void *' much like `char *'.  That is a compiler bug.

Actually, gcc documents its permission of pointer arithmetic on void *
as a feature.  I disagree.  Certainly -ansi -pedantic should complain
about the extension.
-- 
	-Colin

browns@astro.pc.ab.com (Stan Brown, Oak Road Systems) (08/12/90)

In article <1990Aug9.231614.5196@basho.uucp>, john@basho.uucp (John Lacey) writes:
> What operations are legal on pointers to void?

It may help you to think of them as "void pointers" rather than "pointers to
void".  "Pointer to void" sounds too much like "pointer to int" and makes me (at
least) think of a real pointer to a real object of unspecified type.  In fact a
void pointer is just storage in memory where you may later put a pointer to any
type of data.  Only then does the value of the pointer become meaningful.  And
even then, if you're going to do much beyond simple assignments you haave to
use casts.

Do you have a particular use of void* in mind, or is this a general-info
question?

>                                                 K&R2 is it's usual self
> on the matter---no one can tell if what they say is possible, required, 
> complete, a couple of examples, or what.

Hey--don't insult my religion!  :-)

Stan Brown, Oak Road Systems, (216) 371-0043
The opinions expressed are mine. Mine alone!  Nobody else is responsible for
them or even endorses them--except my cat Dexter, and he signed the power of
attorney only under my threat to cut off his Cat Chow!

darcy@druid.uucp (D'Arcy J.M. Cain) (08/13/90)

In article <482@array.UUCP> colin@array.UUCP (Colin Plumb) writes:
>In article <1990Aug10.165644.9238@zoo.toronto.edu> henry@zoo.toronto.edu (Henry Spencer) writes:
>> Many compilers, especially old ones with `void *' hastily kludged in,
>> treat `void *' much like `char *'.  That is a compiler bug.
>
>Actually, gcc documents its permission of pointer arithmetic on void *
>as a feature.  I disagree.  Certainly -ansi -pedantic should complain
>about the extension.

I'll buy the argument about -pedantic but in general I think it is useful
to be able to manipulate generic data.  Things like memcpy for example.  We
know that the data can be any type but we want to treat it as bytes.  Perhaps
we need a new type which acts like void * but allows pointer arithmetic based
on the smallest data type supported by the system, usually (but not always)
a byte.

-- 
D'Arcy J.M. Cain (darcy@druid)     |
D'Arcy Cain Consulting             |   MS-DOS:  The Andrew Dice Clay
West Hill, Ontario, Canada         |   of operating systems.
+ 416 281 6094                     |

henry@zoo.toronto.edu (Henry Spencer) (08/14/90)

In article <1990Aug12.231202.23826@druid.uucp> darcy@druid.uucp (D'Arcy J.M. Cain) writes:
>I'll buy the argument about -pedantic but in general I think it is useful
>to be able to manipulate generic data.  Things like memcpy for example.  We
>know that the data can be any type but we want to treat it as bytes.  Perhaps
>we need a new type which acts like void * but allows pointer arithmetic based
>on the smallest data type supported by the system...

It's called `char *'. :-)  The various tricky implementations in which it
would not be a valid "generic pointer" have pretty well all been outlawed
by various rules in ANSI C.  Note that `void *' and `char *' are constrained
to have the same representation.
-- 
It is not possible to both understand  | Henry Spencer at U of Toronto Zoology
and appreciate Intel CPUs. -D.Wolfskill|  henry@zoo.toronto.edu   utzoo!henry

johnb@srchtec.UUCP (John Baldwin) (08/15/90)

In article <1990Aug12.231202.23826@druid.uucp> darcy@druid.uucp
  (D'Arcy J.M. Cain) writes:
>know that the data can be any type but we want to treat it as bytes.  Perhaps
>we need a new type which acts like void * but allows pointer arithmetic based
>on the smallest data type supported by the system, usually (but not always)
>a byte.

There is a simple fix to this: you can operate on void pointers by casting
them to a useful type.  For example, perhaps you are writing a function foo()
which can take a pointer to anything, and for some (unspecified) reason,
you want to "bump" the pointer up three bytes....

SOMETYPE   foo( void *myptr, size_t someval, ... )
{
      .
      .

   *((char *)&myptr) += 3;

      .
      .
}
-- 
John T. Baldwin                      |  johnb@srchtec.uucp
Search Technology, Inc.              |  johnb%srchtec.uucp@mathcs.emory.edu
standard disclaimer:                 |  ...uunet!samsung!emory!stiatl!srchtec..
opinions and mistakes purely my own. |  ...mailrus!gatech!stiatl!srchtec...

karl@haddock.ima.isc.com (Karl Heuer) (08/16/90)

In article <1990Aug12.231202.23826@druid.uucp> darcy@druid.uucp (D'Arcy J.M. Cain) writes:
>Perhaps we need a new type which acts like void * but allows pointer
>arithmetic based on the smallest data type supported by the system, usually
>(but not always) a byte.

Trouble is, there's no convenient way to describe the operation of
incrementing a pointer by less than a byte, since `sizeof(char)' is
required to be exactly 1.  (This, in turn, is really caused by the
unfortunate overloading of `char' for three logically distinct types;
but it's much too late to fix that.)

Karl W. Z. Heuer (karl@kelp.ima.isc.com or ima!kelp!karl), The Walking Lint

karl@haddock.ima.isc.com (Karl Heuer) (08/16/90)

In article <174@srchtec.UUCP> johnb@srchtec.UUCP (John Baldwin) writes:
>	void *myptr; ... *((char *)&myptr) += 3;

The cast should be to `char **', and it won't work if `myptr' is a register.
I think `myptr = (void *)((char *)myptr + 3);' is better, or (if all the
operations are on the same datatype anyway) just make a `char *' copy of the
original pointer and use it exclusively.

Karl W. Z. Heuer (karl@kelp.ima.isc.com or ima!kelp!karl), The Walking Lint

darcy@druid.uucp (D'Arcy J.M. Cain) (08/16/90)

In article <174@srchtec.UUCP> johnb@srchtec.UUCP (John Baldwin) writes:
>In article <1990Aug12.231202.23826@druid.uucp> darcy@druid.uucp
>  (D'Arcy J.M. Cain) writes:
>>know that the data can be any type but we want to treat it as bytes.  Perhaps
>>we need a new type which acts like void * but allows pointer arithmetic based
>>on the smallest data type supported by the system, usually (but not always)
>>a byte.
>
>There is a simple fix to this: you can operate on void pointers by casting
>them to a useful type.  For example, perhaps you are writing a function foo()

I understand how to cast.  All I am saying is that it shouldn't be necessary.
I find casts to be clumsy and try to avoid them wherever I can.  I think
it is better to define your functions and data types so that any conversion
is automatically done by the compiler.  If the language supported pointer
arithmetic on void * (or supplied another data type with the same features)
this would be possible.  Note that GNU C does support it and I can't see any
harm in it.  ANSI code that doesn't know about it runs just fine but if you
use the feature you do no harm either.

So can anyone suggest any reason why supporting this feature would break
code or otherwise be a problem.  Of course code which used this feature
would be unportable but what other problems would this cause?

-- 
D'Arcy J.M. Cain (darcy@druid)     |
D'Arcy Cain Consulting             |   MS-DOS:  The Andrew Dice Clay
West Hill, Ontario, Canada         |   of operating systems.
+ 416 281 6094                     |

karl@haddock.ima.isc.com (Karl Heuer) (08/17/90)

In article <1990Aug16.014947.1999@druid.uucp> darcy@druid.uucp (D'Arcy J.M. Cain) writes:
>If the language supported pointer arithmetic on void * this would be
>possible.  Note that GNU C does support it and I can't see any harm in it.

The potential harm is when somebody writes code like
	vp = (struct foo *)vp;
	... ++vp ...
without realizing that it doesn't do what was intended.  (Somebody *did*
recently post code much like this, in fact.)  This type of error will be
caught by the ANSI rule, which makes sense because `void' is an incomplete
type of undefined size.

Karl W. Z. Heuer (karl@kelp.ima.isc.com or ima!kelp!karl), The Walking Lint