Void question

M

mark

Hi
What is the principle reason why I cant define a void variable, eg

void x; // gives error
 
K

Keith Thompson

mark said:
What is the principle reason why I cant define a void variable, eg

void x; // gives error

Why should you be able to? What would you expect to be able to do
with it?
 
J

jameskuyper

mark said:
Hi
What is the principle reason why I cant define a void variable, eg

void x; // gives error

If you were allowed to create a void variable, what would you want to
do with it, and why would you expect to be able to do it?
 
F

Flash Gordon

Keith said:
Why should you be able to? What would you expect to be able to do
with it?

Or if you want a slightly more technical answer, because void is an
"incomplete type" which basically means it does not provide enough
information to know what the variable is, or more importantly, what size
it is. If the compiler does not know the size of x then how can it
allocate space for it?

I know Keith knows all this, probably better than I do.
 
B

Beej Jorgensen

mark said:
What is the principle reason why I cant define a void variable, eg

void x; // gives error

void is an incomplete type (and it can't be completed).

-Beej
 
K

Keith Thompson

Mark McIntyre said:
I should imagine he wants to create a typeless variable, and he
expects to later on be able to munge it into a specific type via some
mechanism - perhaps by runtime type conversion when first used. I
believe some languages with a V in their name and possibly ending in
script support this.

Perhaps, but I'd rather hear what the OP had in mind.
To the OP: you can't do it because it doesn't have any meaning. The C
standard defines an expression of type void as having a nonexistent
value (not a value of zero, but no value) and states that this value
is unusable.

Don't be confused by void*, this is a special notation to allow
conversion between pointers of different non-void types.

The void keyword means several things. The standard treats it as
in incomplete type that cannot be completed, but that doesn't cover
all the ways the keyword is used. (I'd almost argue that void isn't
*really* a type.)

void* is a special pointer type. You can't dereference a void*
pointer, but you can convert an arbitrary pointer value to void*
and back again without loss of information (this doesn't apply to
function pointer types), and such conversions can be done implicitly
without a cast.

You can declare a function's return type as void. This doesn't
really mean that it returns a result of type void; it means that
it doesn't return a result.

The void keyword is used in a function prototype to indicate that
it has no parameters:

int no_params(void);

This is a special use of the void keyword, not directly related to
the incomplete type. It's necessary because a function declaration
with empty parentheses already had a meaning in pre-ANSI C.

An expression can be converted to type void with a cast.
This doesn't really convert the expression's result to type void;
rather, it discards the result.

The authors of the standard could have chosen to use a distinct
syntax for each of these things rather than using the pseudo-type
void.
 
K

Keith Thompson

pete said:
void isn't an *object type*.

Yes, I know, and I know that the standard calls it a type.

My point was the standard *could* have been written without defining
"void" as a type (though I'm not arguing that it should have been).
 
P

Phil Carmody

Keith Thompson said:
Why should you be able to? What would you expect to be able to do
with it?

Take the address of it, and know that it was both a valid address,
and not equal to any other address in the system, so that it could
be compared and contrasted using == and != against both addresses
of tangible objects and also other such addresses.

Why one would want to do that is a slightly harder question.

Phil
 
K

Keith Thompson

Phil Carmody said:
Take the address of it, and know that it was both a valid address,
and not equal to any other address in the system, so that it could
be compared and contrasted using == and != against both addresses
of tangible objects and also other such addresses.

"char x;" could serve the same purpose.

The question is, what could you do with "void x;" that you couldn't
either by declaring x as some other type, or by not declaring it at
all?
 
M

mark

Hi
It should be what you get when dereferencering a void*, eg a generic
variable of any type (like Variant in Visual Basic).
 
P

Phil Carmody

Please don't top-post, it's wrong-headed. Correcting.
Hi
It should be what you get when dereferencering a void*, eg a generic
variable of any type (like Variant in Visual Basic).

You cannot dereference a void*. Therefore you shouldn't get a void,
as you don't get anything when you don't do anything. And a void,
not that it exists as an object type, is nothing like a Variant in
VB, which is more like a union of many types.

Phil
 
B

bartc

Phil Carmody said:
Please don't top-post, it's wrong-headed. Correcting.



You cannot dereference a void*. Therefore you shouldn't get a void,
as you don't get anything when you don't do anything. And a void,
not that it exists as an object type, is nothing like a Variant in
VB, which is more like a union of many types.

In that sort of language a Void is usually a value (often meaning
unassigned), although it can also be considered a type consisting of just
that one value.

A Variant being a union of types: that sounds too simplistic, but going
along with that, the following code tries to implement a trivial sort of
variant in C.

In this code, Void is a considered a type, as stored in the tag. But notice
the list of fields in Values union has a corresponding field for each type
tag, except for VOID, which does not need a value; it *is* a value. If that
makes sense..

#include <stdio.h>

typedef enum {VOID=0, INT, FLOAT, CHAR, POINTER, ETC} Tag;

typedef union {
int i;
double f;
char c;
void *p;
} Values;

typedef struct {
Tag tag;
Values values;
} Variant;

void printvariant(char*, Variant);

int main(void){

Variant a = {VOID};
Variant b = {INT};
b.values.i = 1057; /* How do you initialise this struct? */

printvariant("A = ",a);
printvariant("B = ",b);

}

void printvariant(char* caption, Variant x){
printf(caption);
switch (x.tag) {
case VOID:
printf("Void\n"); return;
case INT:
printf("%d\n",x.values.i); return;
default:
printf("Other: %d\n",x.tag);
}
}
 
M

mark

Hi
In that case C is missing a trick IMO, the Variant datatype is
exceptionally powerful in VB and all thats needed is a simple extension of
syntax.
 
J

jameskuyper

mark said:
Hi
In that case C is missing a trick IMO, the Variant datatype is
exceptionally powerful in VB and all thats needed is a simple extension of
syntax.

Oh no - a lot more than that is needed. Languages that provide such a
feature need a lot of additional machinery in order to make it work;
some of it syntactic, but a lot of it is semantic.. The easiest way to
demonstrate this would be to have you give us an example of code that
you would like to be able to write, making use of a void data type in
C. Then we can tell you just what would have to be added to the C
language and to the typical C implementation in order ot make it work.
I'm not saying it can't be done. Just that doing so would require
major changes both to the C standard and to typical C implementations,
changes that in many cases would make it unacceptably inefficient for
many of the uses it is currently popular for.
 
J

jacob navia

mark said:
Hi
In that case C is missing a trick IMO, the Variant datatype is
exceptionally powerful in VB and all thats needed is a simple extension of
syntax.

But you *can* do that in C. Just read the include files where that
VARIANT is defined. In oaidl.h we find:

struct _VARIANT {
union {
struct __tagVARIANT {
VARTYPE vt;
WORD wReserved1;
WORD wReserved2;
WORD wReserved3;
union {
LONG lVal;
BYTE bVal;
SHORT iVal;
FLOAT fltVal;
DOUBLE dblVal;
VARIANT_BOOL boolVal;
_VARIANT_BOOL bool;
unsigned long long ullVal;
SCODE scode;
CY cyVal;
DATE date;
BSTR bstrVal;
IUnknown *punkVal;
IDispatch *pdispVal;
SAFEARRAY *parray;
BYTE *pbVal;
SHORT *piVal;
LONG *plVal;
FLOAT *pfltVal;
DOUBLE *pdblVal;
VARIANT_BOOL *pboolVal;
_VARIANT_BOOL *pbool;
SCODE *pscode;
CY *pcyVal;
DATE *pdate;
BSTR *pbstrVal;
IUnknown **ppunkVal;
IDispatch **ppdispVal;
SAFEARRAY **pparray;
VARIANT *pvarVal;
PVOID byref;
CHAR cVal;
USHORT uiVal;
ULONG ulVal;
INT intVal;
UINT uintVal;
DECIMAL *pdecVal;
CHAR *pcVal;
USHORT *puiVal;
ULONG *pulVal;
INT *pintVal;
UINT *puintVal;
} __VARIANT_NAME_3;
} __VARIANT_NAME_2;
DECIMAL decVal;
} __VARIANT_NAME_1;
};
This is a structure that contains a union of all types that Microsoft
wanted to use in a variant. You can design similar structures in C:

struct myVariant {
union {
// put all the types that you want here
};
};
 
N

Nick Keighley

mark wrote:

Oh no - a lot more than that is needed. Languages that provide such a
feature need a lot of additional machinery in order to make it work;
some of it syntactic, but a lot of it is semantic.. The easiest way to
demonstrate this would be to have you give us an example of code that
you would like to be able to write, making use of a void data type in
C. Then we can tell you just what would have to be added to the C
language and to the typical C implementation in order ot make it work.
I'm not saying it can't be done. Just that doing so would require
major changes both to the C standard and to typical C implementations,
changes that in many cases would make it unacceptably inefficient for
many of the uses it is currently popular for.

you can comeup with some hard questions straight away (as I'm sure
jameskuyper is aware).

Can a void variable hold any type? structs can get pretty big.
Any primitive type? This means we may not need the union trick
for malloc() (what is returned from malloc must be correctly
aligned for any type and one to do this is to return a union
ofall the primitive types).

This is really an "ask Dennis Richie" question.
 
B

Bart

mark wrote:

But you *can* do that in C. Just read the include files where that
VARIANT is defined. In oaidl.h we find:

struct _VARIANT {
         union {
         struct __tagVARIANT {
         VARTYPE vt;
         WORD wReserved1;
         WORD wReserved2;
         WORD wReserved3;
         union {
         LONG lVal; .....

This is a structure that contains a union of all types that Microsoft
wanted to use in a variant. You can design similar structures in C:

struct myVariant {
        union {
                // put all the types that you want here
        };

That big struct was designed to implement /another/ language, where
all the untidy implementations details are hidden away.

Trying to use it directly in C code is not going to be pretty, without
some extra support.

Especially when you also want to add your user-defined structs to the
list of variant types.
 
J

jacob navia

Bart said:
That big struct was designed to implement /another/ language, where
all the untidy implementations details are hidden away.

Trying to use it directly in C code is not going to be pretty, without
some extra support.

Especially when you also want to add your user-defined structs to the
list of variant types.

Nonsense, specially when you use macros to access the member you want.
Basically, this structure lays out clearly what is all about, like
alwys in C the language is transparent.
 
B

Bart

Nonsense, specially when you use macros to access the member you want.
Basically, this structure lays out clearly what is all about, like
alwys in C the language is transparent.- Hide quoted text -

I meant, when trying to use variants as part of a C program, not
writing a C program to implement an interpreter for Basic:

Variant a,b,c; /* decls usually optional */
a=("One","Two","Three");
b="Four";
c=a+b;
printf("C = %V\n",c);
a=1; /* etc *

A lot of support is needed in standard C, to achieve the above rather
than a mess of function calls. Even just limiting variants to simple
types and forgetting those requiring heap management.

Some of this might be possible in your extended C, and probably most
of it in C++, but variants and their ilk belong elsewhere.
 

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,995
Messages
2,570,236
Members
46,822
Latest member
israfaceZa

Latest Threads

Top