Void variables

T

Tim Rentsch

James Kuyper said:
James Kuyper said:
On 05/22/2012 05:32 AM, BartC wrote: [Re: an object of void type]
It wouldn't have any values. Or rather, it would only have one.

You were right the first time. "one value" is one more than the number
specified by the standard: "The void type comprises an empty set of
values" (6.2.5p19).

An 8-bit type has 256 distinct values. An N-bit one would have 2**N values.

Since a 'void' type would have zero bits, that suggests it would have 2**0
values, or just one.

The standard does not say that objects of void type require zero bits;
it says that objects cannot have that type. [snip]

It doesn't, at least not that I could find. More specifically,
AFAICT the following program

int
main(){
void x;
return 0;
}

may be accepted by a conforming implementation, with
no diagnostic messages required.
 
J

Joe Pfeiffer

Tim Rentsch said:
James Kuyper said:
On 05/22/2012 05:32 AM, BartC wrote: [Re: an object of void type]
It wouldn't have any values. Or rather, it would only have one.

You were right the first time. "one value" is one more than the number
specified by the standard: "The void type comprises an empty set of
values" (6.2.5p19).

An 8-bit type has 256 distinct values. An N-bit one would have 2**N values.

Since a 'void' type would have zero bits, that suggests it would have 2**0
values, or just one.

The standard does not say that objects of void type require zero bits;
it says that objects cannot have that type. [snip]

It doesn't, at least not that I could find. More specifically,
AFAICT the following program

int
main(){
void x;
return 0;
}

may be accepted by a conforming implementation, with
no diagnostic messages required.

If I'm reading correctly:

6.2.5 Types
19 The void type comprises an empty set of values; it is an incomplete
object type that cannot be completed.

6.7.2.1 Structure and union specifiers
3 A structure or union shall not contain a member with incomplete or
function type (hence, a structure shall not contain an instance of
itself, but may contain a pointer to an instance of itself), except
that the last member of a structure with more than one named member
may have incomplete array type; such a structure (and any union
containing, possibly recursively, a member that is such a structure)
shall not be a member of a structure or an element of an array.

5.1.1.3 Diagnostics
1 A conforming implementation shall produce at least one diagnostic
message (identified in an implementation-defined manner) if a
preprocessing translation unit or translation unit contains a
violation of any syntax rule or constraint, even if the behavior is
also explicitly specified as undefined or
implementation-defined. Diagnostic messages need not be produced in
other circumstances.
 
T

Tim Rentsch

Joe Pfeiffer said:
Tim Rentsch said:
James Kuyper said:
On 05/22/2012 12:08 PM, BartC wrote:


On 05/22/2012 05:32 AM, BartC wrote:
[Re: an object of void type]
It wouldn't have any values. Or rather, it would only have one.

You were right the first time. "one value" is one more than the number
specified by the standard: "The void type comprises an empty set of
values" (6.2.5p19).

An 8-bit type has 256 distinct values. An N-bit one would have 2**N values.

Since a 'void' type would have zero bits, that suggests it would have 2**0
values, or just one.

The standard does not say that objects of void type require zero bits;
it says that objects cannot have that type. [snip]

It doesn't, at least not that I could find. More specifically,
AFAICT the following program

int
main(){
void x;
return 0;
}

may be accepted by a conforming implementation, with
no diagnostic messages required.

If I'm reading correctly:

6.2.5 Types
19 The void type comprises an empty set of values; it is an incomplete
object type that cannot be completed.

6.7.2.1 Structure and union specifiers
3 A structure or union shall not contain a member with incomplete or
function type (hence, a structure shall not contain an instance of
itself, but may contain a pointer to an instance of itself), except
that the last member of a structure with more than one named member
may have incomplete array type; such a structure (and any union
containing, possibly recursively, a member that is such a structure)
shall not be a member of a structure or an element of an array.

5.1.1.3 Diagnostics
1 A conforming implementation shall produce at least one diagnostic
message (identified in an implementation-defined manner) if a
preprocessing translation unit or translation unit contains a
violation of any syntax rule or constraint, even if the behavior is
also explicitly specified as undefined or
implementation-defined. Diagnostic messages need not be produced in
other circumstances.

The example program has no structs or unions in
it, so 6.7.2.1 doesn't apply.
 
J

Jens Gustedt

Am 23.05.2012 01:14, schrieb Tim Rentsch:
The example program has no structs or unions in
it, so 6.7.2.1 doesn't apply.

But 6.7 para 7 applies

If an identifier for an object is declared with no linkage, the type for
the object shall be
complete by the end of its declarator, or by the end of its
init-declarator if it has an
initializer; in the case of function parameters (including in
prototypes), it is the adjusted
type (see 6.7.6.3) that is required to be complete.

Jens
 
H

Hans Vlems

As others have pointed out, you can't do this.  This is one of those
questions that leads me to believe that there's something else you're
actually trying to do, and declaring a variable of type void seems like
a way to achive that underlying goal.  So...  what are you really trying
to do?

Writing obfuscated C very likely.
Hans
 
S

somenath

Am 23.05.2012 01:14, schrieb Tim Rentsch:


But 6.7 para 7 applies

If an identifier for an object is declared with no linkage, the type for
the object shall be
complete by the end of its declarator, or by the end of its
init-declarator if it has an
initializer; in the case of function parameters (including in
prototypes), it is the adjusted
type (see 6.7.6.3) that is required to be complete.

Out my curiosity when I compiled the following program I did not get
any diagnostic for the incomplete type. So Will v be treated as
complete type then ?

int main(void)
{
extern void v;

return 0;
}

$ gcc -ansic -pedantic -Wall voidTest.c
voidTest.c: In function `main':
voidTest.c:5: warning: unused variable `v'


Also please see the following program
#include<stdio.h>

extern void v;

int main(void)
{
int v = 2;
printf("Value of v = %d\n",v);
return 0;
}

The Out put is
Value of v = 2
So is the type of v getting changed dynamically from incomplete to
complete type ?
 
V

Vallabha

Hello

I would like to define a variable of void type. However I get compiler
errors:

void x; // error: variable or field ‘x’ declared void

Infact there is a typedef and I want to allow the defined type to be,
void. However, the error is the same.

Thankyou

You can only declare pointers of type void *. In my understanding when
we declare a variable of some type (int/float etc) compiler knows how
much space has to be set aside for this variable. However compiler
will have no clue how much space is required for a void variable.

Cheers,
-Vallabha
 
T

Tim Rentsch

Jens Gustedt said:
Am 23.05.2012 01:14, schrieb Tim Rentsch:

But 6.7 para 7 applies

If an identifier for an object is declared with no linkage,
the type for the object shall be complete by the end of its
declarator, or by the end of its init-declarator if it has an
initializer; in the case of function parameters (including in
prototypes), it is the adjusted type (see 6.7.6.3) that is
required to be complete.

This paragraph is listed under Semantics, not Constraints. The
example program has undefined behavior, but it is still an
admissible program, ie, acceptable with no diagnostics by a
conforming implementation, under which its behavior could
be defined by the implementation to be something perfectly
reasonable.
 
E

Eric Sosman

The other posters are wrong.

You can declare a void variable in C, just like this:

void x;

Hmmm. When I put that into a one-line source file, gcc says

foo.c:1: error: storage size of 'x' isn't known
Compilation exited abnormally with code 1 at Wed May 23 09:44:17

So: gcc bug?
Here is a small program illustrating the proper usage of a void
variable.

void x;

void a(int a)
{
}

int b(void)
{
return(0);
}


int main(void)
{
int rv;

x = a(3);
rv = b(x);
}

gcc has even more to say about this one:

foo.c: In function 'main':
foo.c:17: error: 'x' has an incomplete type
foo.c:18: error: too many arguments to function 'b'
Compilation exited abnormally with code 1 at Wed May 23 09:48:28

Another gcc bug? Perhaps you should contact the gcc people and
give them the benefit of your superior knowledge of C.

Or maybe, just maybe, "the other posters are wrong" is wrong.
 
E

Eric Sosman

Because C uses a 'void' type to identify those functions which are really
procedures.

It further overloads 'void' in a function signature, to specify functions
(or procedures) with 0 parameters, rather than an unknown number.

I agree C could have maybe done more with 'void', after having invented it.

"Hysterical raisins."

Original C had no `void' type at all. A function returning no
value simply omitted specifying a return type (which formally declared
that it returned `int'), and the caller simply knew to ignore whatever
garbage happened to land in the conventional place for `int' results.

Also, malloc() et al. were usually declared as returning `char*'
("usually," because the usual suite of system-provided headers usually
had no malloc() declaration). This may be why we still see people
applying casts to malloc() results: In the days when the results
were `char*' and needed to be assigned to a `struct foo*', the cast
was in fact necessary.

A third thing: In original C, there was no way to describe a
function's parameter list to its callers. You simply said "This is
a function returning a `foobar'; read the documentation if you
want to know how to call it. (Oh, yeah, I'll write the documentation
Real Soon Now.)"

Along came the Committee that developed the ANSI Standard, and
they saw that "ignore the `int' that wasn't returned" was fragile, and
could even be burdensome for some implementations (they might need to
set aside a place for the non-existent result, or might need to use
up a CPU register to not hold it). They also wanted to fix up the
cast-malloc() mess, and to borrow the C++ idea of describing the
parameter lists in a way the compiler could use. And thus were born
the three uses of `void':

- You could declare a function as "returning `void'", which truly
means it returns nothing at all. (No, not even a vacuous value.)
Hooray! C got procedures that were recognizable as such.

- You could declare pointers to the non-instantiable `void' type,
and then you could introduce special rules for silent conversion of
such pointers to all other data pointer types. Hooray! All those
malloc() casts became unnecessary, *and* the compiler could still
diagnose failures to declare malloc() properly. (And a Standard
declaration was inserted into a brand-new header, too.)

- Ah, but the parameter lists were a bit of a problem. The empty
list `()' didn't really mean "no parameters," but "parameters in the
style of traditional C, that is, we don't know what they are or how
many." It would be nice to get rid of the traditional meaning of `()'
and co-opt it as meaning "no parameters," but this would invalidate
just about all the C code that had been written in the prior twenty-
odd years. Hence, a kludge: `()' retained its traditional meaning,
while `(void)' was invented to mean what `()' "should" have meant.

And that, O Best Beloved, is how the Ritchie's Child got his trunk.
 
B

Bartc

Think about it ... why would the C language designers have allowed the
return type of "void" unless they wanted this to be assignable to a
variable of type "void"?

Because C uses a 'void' type to identify those functions which are really
procedures.

It further overloads 'void' in a function signature, to specify functions
(or procedures) with 0 parameters, rather than an unknown number.

I agree C could have maybe done more with 'void', after having invented it.
 
J

Joachim Schmitz

somenath said:
Out my curiosity when I compiled the following program I did not get
any diagnostic for the incomplete type. So Will v be treated as
complete type then ?

int main(void)
{
extern void v;

This only declares it but doesn't define nor use it
return 0;
}

$ gcc -ansic -pedantic -Wall voidTest.c
voidTest.c: In function `main':
voidTest.c:5: warning: unused variable `v'


Also please see the following program
#include<stdio.h>

extern void v;

int main(void)
{
int v = 2;

This 'shadows' the prev declarion with a new variable
printf("Value of v = %d\n",v);
return 0;
}

The Out put is
Value of v = 2
So is the type of v getting changed dynamically from incomplete to
complete type ?

No
 
J

Joel C. Salomon

I would like to define a variable of void type. However I get compiler
errors:

void x; // error: variable or field ‘x’ declared void

Infact there is a typedef and I want to allow the defined type to be,
void. However, the error is the same.

The problem is that void variables cannot be named; more formally, a
void object can never be an lvalue. (This is why you cannot dereference
a void* pointer.) Unfortunately, the line

void /* no variable name */ ;

is not valid. This was due to a bug in the original C grammar, kept for
backward compatibility reasons. ANSI therefore defined a special syntax

(void) 0;

for the operation you want.

--Joel

P.S. Exercise: Which of my claims above are (a) correct, (b) *almost*
correct but misleadingly phrased or otherwise subtly wrong, or (c)
outright lies?
 
J

James Kuyper

Hello

I would like to define a variable of void type. However I get compiler
errors:

void x; // error: variable or field ‘x’ declared void

Infact there is a typedef and I want to allow the defined type to be,
void. However, the error is the same.

It just occurred to me what your last paragraph might mean. Are you
trying to to this:

typedef void x;

If so, you shouldn't be getting the same error message.
 
J

James Kuyper

The problem is that void variables cannot be named; more formally, a
void object can never be an lvalue. (This is why you cannot dereference
a void* pointer.) Unfortunately, the line

void /* no variable name */ ;

is not valid. This was due to a bug in the original C grammar, kept for
backward compatibility reasons. ANSI therefore defined a special syntax

(void) 0;

for the operation you want.

He didn't say anything about wanting an operation of any kind - most of
the responses have asked him what he actually wants to do
He has said that "I would like to define a variable of void type; what
you've provided is an expression-statement, not a definition of a variable.
 
R

Raj Pashwar

there is no such thing as a void type. What do you think it means. If
you explain we might be able to tell you how to achieve what you want
some other way.

Thanks for the many replies, just got back from a trip. Sorry I don't
have time to read them all fully, this thread has got too long.

The situation is this: I have a typedef'd variable. This might be
typedef'd to say FILE*:

typedef FILE* mytype;

and then the code
mytype x;

compiles fine.

However, if instead it is typedef'd to void:

typedef void mytype;

then the same code
mytype x;

no longer compiles.

I hope this is clearer.

Cheers Raj
 
E

Eric Sosman

Thanks for the many replies, just got back from a trip. Sorry I don't
have time to read them all fully, this thread has got too long.

Oh, I see. *We* can spend *our* time writing answers to your
question, but *you* can't be bothered to read them? Sweet ...
The situation is this: I have a typedef'd variable. This might be
typedef'd to say FILE*:

typedef FILE* mytype;

and then the code
mytype x;

compiles fine.

However, if instead it is typedef'd to void:

typedef void mytype;

then the same code
mytype x;

no longer compiles.

I hope this is clearer.

Several respondents have explained why it won't compile.

One thing remains UNclear: What are you trying to achieve?
The meaningless `void x;' (in whatever spelling) won't help, so
simply repeating that it doesn't gets us nowhere. Tell us what
you want to accomplish, and someone will quite likely suggest an
approach that will get you nearer your goal.

Assuming you take the trouble to read the suggestion, that is.
 
J

James Kuyper

On 05/25/2012 05:22 PM, Raj Pashwar wrote:
....
The situation is this: I have a typedef'd variable. This might be
typedef'd to say FILE*:

typedef FILE* mytype;

and then the code
mytype x;

compiles fine.

However, if instead it is typedef'd to void:

typedef void mytype;

then the same code
mytype x;

no longer compiles.

I hope this is clearer.

It is.

The simple answer is, you can't do that, and you should re-write your
code to avoid doing it. If it's not obvious how the re-write should be
done, we can give you advice on that matter. But in order to give you
that advice, we would need more information about the context than
you've given us:

Under what circumstances would 'mytype' be void?
What is the purpose of 'x'?

It should be the case that the purpose served by 'x' becomes meaningless
under those circumstances where 'mytype' is void. If not, you've got big
problems; otherwise, something similar to the following example might do
the trick:

#define VOID_MYTYPE

typedef
#ifdef VOID_MYTYPE
void
#else
other_type
#endif
mytype;

mytype *func(
mytype *p
#ifndef VOID_MYTYPE
, mytype x
#endif
){
#ifndef VOID_MYTYPE
*p++ = x;
#endif
// Other operations not involving x
return p;
}

You have to use the #if #else #endif family for this purpose, you can't
use if(){}else{}, because the definitions of 'x' and 'y' are constraint
violations if mytype is void. You must make sure that they don't even
exist anymore after preprocessing is complete, if that is the case.
 
J

Joe Pfeiffer

Raj Pashwar said:
Thanks for the many replies, just got back from a trip. Sorry I don't
have time to read them all fully, this thread has got too long.

The situation is this: I have a typedef'd variable. This might be
typedef'd to say FILE*:

typedef FILE* mytype;

and then the code
mytype x;

compiles fine.

However, if instead it is typedef'd to void:

typedef void mytype;

then the same code
mytype x;

no longer compiles.

I hope this is clearer.

No, it was perfectly clear the first time. And many people answered the
first time. Why would anyone answer again?
 
R

Raj Pashwar

Oh, I see. *We* can spend *our* time writing answers to your
question, but *you* can't be bothered to read them? Sweet ...


Several respondents have explained why it won't compile.

One thing remains UNclear: What are you trying to achieve?
The meaningless `void x;' (in whatever spelling) won't help, so simply
repeating that it doesn't gets us nowhere. Tell us what you want to
accomplish, and someone will quite likely suggest an approach that will
get you nearer your goal.

Assuming you take the trouble to read the suggestion, that is.

OK, I will explain, but I didn't think these details are relevant.

The program has a LOG functionality. This may be enabled, then log_t will
be FILE* pointing to the LOG location. Or it may be unenabled when log_t
must be void typed.

It appears a workaround may be needed here.

Cheers Raj
 

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

Forum statistics

Threads
474,079
Messages
2,570,574
Members
47,207
Latest member
HelenaCani

Latest Threads

Top