void vs void* (philosophical question)

  • Thread starter Giannis Papadopoulos
  • Start date
G

Giannis Papadopoulos

According to the standard (ISO C99 draft WG14/N1124), void is the
incomplete type that cannot be completed and comprises the empty set of
values. Since it declares the absense of a value can it be considered a
data type?

Regarding void*, is it just a simple reuse of the same keyword (void) or
they have a closer relationship? I could think of only one - a pointer
to an incomplete type. However, if one could say that void is the
absense of a value, how can we have a pointer to something that does not
exist?


--
one's freedom stops where others' begin

Giannis Papadopoulos
Computer and Communications Engineering dept. (CCED)
University of Thessaly
http://dop.freegr.net/
 
M

Mark F. Haigh

Giannis said:
According to the standard (ISO C99 draft WG14/N1124), void is the
incomplete type that cannot be completed and comprises the empty set of
values. Since it declares the absense of a value can it be considered a
data type?

Regarding void*, is it just a simple reuse of the same keyword (void) or
they have a closer relationship? I could think of only one - a pointer
to an incomplete type. However, if one could say that void is the
absense of a value, how can we have a pointer to something that does not
exist?

Here's my best explanation:

A void * is a pointer to (just about) anything. If you dereference a
void *, you might be referring to a 32 bit integer or a 128 bit
floating point value. You might be referring to a structure or a
union. You might be referring to damn near __anything__. In C, you do
the bookkeeping, not the compiler (usually).

Since a void * may point to just about anything, it's safest for the
compiler to treat it as if it points to __nothing in particular__. You
must convert a void * to another pointer type before using it:

#include <stdio.h>

int main(void)
{
int a = 42;
void *p = &a;
printf("%d\n", *(int *) p);
return 0;
}

[mark@icepick]$ gcc -ansi -pedantic -Wall -O2 -o foo foo.c
[mark@icepick]$ ./foo
42


Mark F. Haigh
(e-mail address removed)
 
G

Giannis Papadopoulos

Mark said:
Giannis said:
According to the standard (ISO C99 draft WG14/N1124), void is the
incomplete type that cannot be completed and comprises the empty set of
values. Since it declares the absense of a value can it be considered a
data type?

Regarding void*, is it just a simple reuse of the same keyword (void) or
they have a closer relationship? I could think of only one - a pointer
to an incomplete type. However, if one could say that void is the
absense of a value, how can we have a pointer to something that does not
exist?

Here's my best explanation:

A void * is a pointer to (just about) anything. If you dereference a
void *, you might be referring to a 32 bit integer or a 128 bit
floating point value. You might be referring to a structure or a
union. You might be referring to damn near __anything__. In C, you do
the bookkeeping, not the compiler (usually).

Since a void * may point to just about anything, it's safest for the
compiler to treat it as if it points to __nothing in particular__. You
must convert a void * to another pointer type before using it:

#include <stdio.h>

int main(void)
{
int a = 42;
void *p = &a;
printf("%d\n", *(int *) p);
return 0;
}

[mark@icepick]$ gcc -ansi -pedantic -Wall -O2 -o foo foo.c
[mark@icepick]$ ./foo
42


Mark F. Haigh
(e-mail address removed)

I do not want to know about the usage of void and void*. I want to know
if they have some common meaning, apart from the first 4 letters.

Thanks anyway however.

--
one's freedom stops where others' begin

Giannis Papadopoulos
Computer and Communications Engineering dept. (CCED)
University of Thessaly
http://dop.freegr.net/
 
R

Richard Heathfield

Giannis Papadopoulos said:
According to the standard (ISO C99 draft WG14/N1124), void is the
incomplete type that cannot be completed and comprises the empty set of
values. Since it declares the absense of a value can it be considered a
data type?

Regarding void*, is it just a simple reuse of the same keyword (void)
Yes.

or they have a closer relationship? I could think of only one - a pointer
to an incomplete type.

Apart from that, they pretty much mean *opposite* things. void means
"nothing", and void * means "pointer to anything" (in the "whaddya mean,
what am I pointing at? How should I know?" sense).
However, if one could say that void is the
absense of a value, how can we have a pointer to something that does not
exist?

If void means "absence of value", surely void * means "a pointer which you
can't dereference because to do so would yield the absence of a value".

But yes, it's sticky-icky. I'd have bitten the bullet and introduced a new
keyword, e.g. object, which I'd have used to replace void in pointer
contexts. Thus: object *malloc(size_t), etc.

You can do this easily enough in your own code with:

#define object void /* possible; just not very wise */

But I am NOT advocating this! :) If the language supported it, that would
be different, but it doesn't.
 
I

Ian Malone

Giannis said:
I do not want to know about the usage of void and void*. I want to know
if they have some common meaning, apart from the first 4 letters.

My 2 pence: void is an incomplete type, a pointer to the incomplete
type must be able to point to any possible object, therefore void *
must be the generic pointer.

Consider analogously the pointer to an incomplete struct.
 
B

Ben C

Mark said:
Here's my best explanation:

A void * is a pointer to (just about) anything. If you dereference a
void *, you might be referring to a 32 bit integer or a 128 bit
floating point value. You might be referring to a structure or a
union. You might be referring to damn near __anything__. In C, you do
the bookkeeping, not the compiler (usually).

Since a void * may point to just about anything, it's safest for the
compiler to treat it as if it points to __nothing in particular__. You
must convert a void * to another pointer type before using it:
[snip]

I do not want to know about the usage of void and void*. I want to know
if they have some common meaning, apart from the first 4 letters.

Thanks anyway however.

I think Mark F. Haigh has elucidated this a bit: "void" means "nothing",
"void *" means "pointer to anything".

Anything != nothing, although anything ~= "nothing in particular". So
they're not the same void. But closely related ideas, so we use the same
keyword.

void * is not quite consistent with void as follows:

int *p;

can be read as "p is a pointer and *p is an int". But:

void *p;

"p is a pointer [true] and *p is a void [false]"
 
P

pete

Giannis said:
According to the standard (ISO C99 draft WG14/N1124),
void is the incomplete type that cannot be completed
and comprises the empty set of values.
Since it declares the absense of a value can it be considered a
data type?

No.

sizeof(void) is undefined.
You can't declare an object of type void.
You can't have an array of type void elements.
An expression of type void can neither be
the left nor right operand of the assignment operator.
 
G

Guest

Ben said:
void * is not quite consistent with void as follows:

int *p;

can be read as "p is a pointer and *p is an int". But:

void *p;

"p is a pointer [true] and *p is a void [false]"

[true] and [true], actually. *p is a valid expression of type void, and
&*p evaluates to p. (Of course, it's pointless to do this except for
very special cases.)
 
T

Thomas J. Gritzan

Giannis said:
According to the standard (ISO C99 draft WG14/N1124), void is the
incomplete type that cannot be completed and comprises the empty set of
values. Since it declares the absense of a value can it be considered a
data type?

Regarding void*, is it just a simple reuse of the same keyword (void) or
they have a closer relationship? I could think of only one - a pointer
to an incomplete type. However, if one could say that void is the
absense of a value, how can we have a pointer to something that does not
exist?

Its logical if you think about it in terms of set theorie.

Think of two structs:

struct person
{
char* name;
};


struct worker
{
char* name;
char* job;
};

A pointer person* can point to a struct person and to a struct worker,
so it is a pointer to "at least a person".

A void* is a pointer to "at least nothing", so it can't point to
effectively everything.

Thomas
 
C

Chris Torek

According to the standard (ISO C99 draft WG14/N1124), void is the
incomplete type that cannot be completed and comprises the empty set of
values. Since it declares the absense of a value can it be considered a
data type?

In a larger, "not Standard C" sense, yes. In Standard C, however,
types are partitioned into "object types", "function types", and
"incomplete types". (The Standard does not define "data type" but
logically it would appear to map to "object type". Interestingly,
my C99 draft *uses* the phrase "data types" in the description of
<wchar.h>, in paragraph 1 of section 7.19.1. It is clear enough
that it does not mean "incomplete types" here. Perhaps the phrasing
was changed in the final standard, though.)

(If I were in charge of things, I would probably make "void" an
ordinary object type whose size is zero, so that sizeof(void) ==
0; its value, upon conversion to any other scalar type, would be
zero. Thus:

void v, *pv = &v;
printf("%d %d\n", v, *pv);

would print "0 0\n". :) Of course, I would also add zero-sized
arrays:

int a[0], b;

with the allowance -- but not requirement -- that &a[0] == &b. Then
I might also remove the "flexible array member" and simply bless the
Struct Hack.)
Regarding void*, is it just a simple reuse of the same keyword (void) or
they have a closer relationship?

As most others have said, it is just reuse of the keyword.
 
K

Kenneth Brody

Chris Torek wrote:
[...]
(If I were in charge of things, I would probably make "void" an
ordinary object type whose size is zero, so that sizeof(void) ==
0; its value, upon conversion to any other scalar type, would be
zero. Thus:
[...]

How would you handle functions which don't return anything?

void foo()
{
void retval;

... do stuff ...

return retval;
}

And how would you resolve the use of an uninitialized variable for
the return?

Would you allow comparing voids, and void arithmetic?

--
+-------------------------+--------------------+-----------------------+
| Kenneth J. Brody | www.hvcomputer.com | #include |
| kenbrody/at\spamcop.net | www.fptech.com | <std_disclaimer.h> |
+-------------------------+--------------------+-----------------------+
Don't e-mail me at: <mailto:[email protected]>
 
C

Chris Torek

How would you handle functions which don't return anything?

void foo()
{
void retval;

... do stuff ...

return retval;
}

Legal, if unnecessarily verbose.
And how would you resolve the use of an uninitialized variable for
the return?

Since objects of type "void" have no bits, it does not matter whether
you initialize them. Their "apparent value" would always be zero.
Assigning any value to a "void" variable throws away its value;
Would you allow comparing voids,

Sure:

void a, b;
if (a == b) /* means "if (0 == 0)" */
...
and void arithmetic?

Yes, with the caveat that any "void" object is alwys zero, so you
cannot divide by a "void":

a + b /* 0 + 0 */
a * 42 /* 0 * 42 */
a / 3 /* 0 / 3 */
a / b /* error, division by zero */

Also, since sizeof(a) == 0 and sizeof(b) == 0, it is possible (but
not required) that &a == &b (or indeed, &a == &anyothervar).

Since sizeof(void) == 0, in this not-quite-C language, arithmetic
on "void *" is also well-defined, and causes nothing to happen:

void *p = malloc(100), *q;
int k = 12;

if (p == NULL) ... handle error ...
q = p + k;
if (q == p)
printf("always true\n");
else
abort();

I think most compilers would warn about arithmetic on "void *",
since the fact that "q = p + k" means the same thing as "q = p"
means that it is not useful to add anything to "p" here. But it
would be allowed.
 
K

Keith Thompson

Chris Torek said:
In a larger, "not Standard C" sense, yes. In Standard C, however,
types are partitioned into "object types", "function types", and
"incomplete types". (The Standard does not define "data type" but
logically it would appear to map to "object type". Interestingly,
my C99 draft *uses* the phrase "data types" in the description of
<wchar.h>, in paragraph 1 of section 7.19.1. It is clear enough
that it does not mean "incomplete types" here. Perhaps the phrasing
was changed in the final standard, though.)

Are you sure about that section number? In both n869 and the final
standard, 7.19 is <stdio.h>; <wchar.h> is 7.24.

In the C99 standard, 7.19.1p1 says:

The header <stdio.h> declares three types, several macros, and
many functions for performing input and output.

and 7.24.1p1 says:

The header <wchar.h> declares four data types, one tag, four
macros, and many functions.
 
K

Keith Thompson

Chris Torek said:
Legal, if unnecessarily verbose.


Since objects of type "void" have no bits, it does not matter whether
you initialize them. Their "apparent value" would always be zero.
Assigning any value to a "void" variable throws away its value;


Sure:

void a, b;
if (a == b) /* means "if (0 == 0)" */
...


Yes, with the caveat that any "void" object is alwys zero, so you
cannot divide by a "void":

a + b /* 0 + 0 */
a * 42 /* 0 * 42 */
a / 3 /* 0 / 3 */
a / b /* error, division by zero */

Also, since sizeof(a) == 0 and sizeof(b) == 0, it is possible (but
not required) that &a == &b (or indeed, &a == &anyothervar).

Since sizeof(void) == 0, in this not-quite-C language, arithmetic
on "void *" is also well-defined, and causes nothing to happen:

void *p = malloc(100), *q;
int k = 12;

if (p == NULL) ... handle error ...
q = p + k;
if (q == p)
printf("always true\n");
else
abort();

I think most compilers would warn about arithmetic on "void *",
since the fact that "q = p + k" means the same thing as "q = p"
means that it is not useful to add anything to "p" here. But it
would be allowed.

I think your not-quite-C language is consistent, or can be made so.
But the major difference between real C and your not-quite-C is that
your language allows certain operations that C doesn't -- and as far
as I can tell, few if any of the additional allowed operations are
useful. (Unless I've missed something, which is always a
possibility.)
 
S

Stephen Sprunk

Kenneth Brody said:
Chris Torek wrote:
[...]
(If I were in charge of things, I would probably make "void" an
ordinary object type whose size is zero, so that sizeof(void) ==
0; its value, upon conversion to any other scalar type, would be
zero. Thus:
[...]

How would you handle functions which don't return anything?

void foo()
{
void retval;

... do stuff ...

return retval;
}

They return void, which is valueless.
And how would you resolve the use of an uninitialized variable for
the return?

Since it's impossible for a void variable to hold any value, all void
variables are initialized by merely declaring them.
Would you allow comparing voids, and void arithmetic?

IMHO, the result of any void comparison or arithmetic is necessarily void,
and could only be assigned to a void variable. Likewise, dereferencing a
void* would result in an expression of type void, which couldn't be assigned
except to a void variable.

Chris diverges from my take, as he appears to consider void an integral type
with no value bits (and possibly no padding bits either), so that if it's
used in a context that requires another integer type, it is promoted to 0.
If you assign a non-void to a void variable, the same rules would apply as
trying to assign INT_MAX+1 to an int.

Either way, I don't see any reason a compiler would do anything with a void
variable other than optimize it out of existence. None of this has any use
other than trying to explain what relation (void*) has to (void).

S
 
C

Chris Torek

Are you sure about that section number? In both n869 and the final
standard, 7.19 is <stdio.h>; <wchar.h> is 7.24.

My draft is considerably older than those two.

(It is, however, in plain-text, a format I find much more suitable
in general.)
In the C99 standard, 7.19.1p1 says:

The header <stdio.h> declares three types, several macros, and
many functions for performing input and output.

and 7.24.1p1 says:

The header <wchar.h> declares four data types, one tag, four
macros, and many functions.

Yes; but the rest of the standard appears not to define the term
"data type" (thus leaving it to other included standards).
 
S

Suman

Chris said:
Legal, if unnecessarily verbose.


Since objects of type "void" have no bits, it does not matter whether
you initialize them. Their "apparent value" would always be zero.
Assigning any value to a "void" variable throws away its value;


Sure:

void a, b;
if (a == b) /* means "if (0 == 0)" */
...


Yes, with the caveat that any "void" object is alwys zero, so you
cannot divide by a "void":

a + b /* 0 + 0 */
a * 42 /* 0 * 42 */
a / 3 /* 0 / 3 */
a / b /* error, division by zero */

Also, since sizeof(a) == 0 and sizeof(b) == 0, it is possible (but
not required) that &a == &b (or indeed, &a == &anyothervar).

Since sizeof(void) == 0, in this not-quite-C language, arithmetic
on "void *" is also well-defined, and causes nothing to happen:

Continuing from where Kenneth Brody left off.
<tongue-in-cheek>
What about the logical operations on void-of-the-TorekC? In case you
allow them too; we'd no longer need `bool' -- would we?
</tongue-in-cheek>
 
D

Dietmar Schindler

pete said:
sizeof(void) is undefined.

It is defined to be a violation of the constraint "The sizeof operator
shall not be applied to an expression that has ... an incomplete type,
to the parenthesized name of such a type, or ..."; so it's prohibited.
 
D

Dave Thompson

Legal, if unnecessarily verbose.
FWIW, <OT> C++ </> does allow a void function to have a return
statement with an expression of void type. Primarily AFAICT for
regularity in (uses aka instantiations of) templates.
Since objects of type "void" have no bits, it does not matter whether
you initialize them. Their "apparent value" would always be zero.
Assigning any value to a "void" variable throws away its value;
So would any void expression be a null pointer constant? <gd&r>

<snip rest>

- David.Thompson1 at worldnet.att.net
 

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

No members online now.

Forum statistics

Threads
473,754
Messages
2,569,528
Members
45,000
Latest member
MurrayKeync

Latest Threads

Top