Size of Void

A

arun

Hi,

Why sizeof operator when applied on void returns one when compiled
with gcc compiler ??. When i tried it on VC++ compiler, it gives an
error. But another version of the VC++ compiler on my friend's machine
gives it as zero. Have anyone tried this ? I believe it should give an
error because i think there is nothing called void.

Regards,
arun..
 
R

Richard Bos

arun said:
Why sizeof operator when applied on void returns one when compiled
with gcc compiler ??.

Because someone on the ganuck team thought that this would be a good
idea. Whatever made this person think that is one of the great mysteries
of the universe, which will be revealed when Deep Thought II finishes
calculating.

Richard
 
G

Guest

Richard said:
Because someone on the ganuck team thought that this would be a good
idea. Whatever made this person think that is one of the great mysteries
of the universe, which will be revealed when Deep Thought II finishes
calculating.

Instead of assuming there is no reason for this, you could check the
documentation, where you would find that sizeof(void) is defined in
"GNU C" because this allows certain extra operations on pointers to
void. Given that gcc complains about this when called with -pedantic,
and -pedantic is documented as a required option to get gcc to try to
conform to any standard, what is your problem with it?
 
R

Richard Bos

=?utf-8?B?SGFyYWxkIHZhbiBExLNr?= said:
Instead of assuming there is no reason for this, you could check the
documentation, where you would find that sizeof(void) is defined in
"GNU C" because this allows certain extra operations on pointers to
void.

Well, yeah, that much was obvious. If sizeof(void) isn't forced to be 1,
you can't do arithmetic on void *s. But whoever thought that arithmetic
on void *s was a good idea?
Given that gcc complains about this when called with -pedantic,
and -pedantic is documented as a required option to get gcc to try to
conform to any standard, what is your problem with it?

None, as long as people don't ask for reasons for Ganuck-specific
features in this ISO C newsgroup.

Richard
 
G

Guest

Richard said:
None, as long as people don't ask for reasons for Ganuck-specific
features in this ISO C newsgroup.
From arun's original post:
"But another version of the VC++ compiler on my friend's machine gives
it as zero."
sizeof(void) is allowed in more compilers than only GNU's, and
additionally, it's not always linked to arithmetic on void * (unless
with that VC++ compiler for any valid void *p and integer i, p+i==p).

Also from the original post:
"I believe it should give an error because i think there is nothing
called void."
Asking whether something is valid C is a problem now in this newsgroup?
I'll admit that particular question is not explicit, but that's how I
read it.

A simple answer without insults would be one that states sizeof(void)
is not allowed in standard C, and therefore if accepted by any compiler
may give any result for any reason.
 
K

Kenneth Brody

Richard Bos wrote:
[... sizeof(void)==1 in gcc ...]
Well, yeah, that much was obvious. If sizeof(void) isn't forced to be 1,
you can't do arithmetic on void *s.

Hmm... On my system, sizeof(int) is 4, and I can do arithmetic on int*'s
all over the place. You can have sizeof(void) be 37 if you wanted, and
arithmetic would still "work" on void*'s.
But whoever thought that arithmetic on void *s was a good idea?

I guess it allows "easy" access to void* buffers? Perhaps:

void foo(void *buffer)
{
int i;
float f;
char *pt;

i = *(int *)buffer;
buffer += sizeof(i);
f = *(float *)buffer;
buffer += sizeof(f);
pt = *(char **)buffer;
buffer += sizeof(pt);

...etc...
}

(Yes, I know this is very dependent on alignment restrictions.)

Of course, given that you need to cast each assignment anyway, why not
just use "unsigned char *" instead?

[...]

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

Rod Pemberton

Richard Bos said:
Well, yeah, that much was obvious. If sizeof(void) isn't forced to be 1,
you can't do arithmetic on void *s.

Really? As I see it, since sizeof(void) and pointer arithmetic are
undefined by the C standards, the compiler is free to return zero (or as
Brody said 37, or McIntyre would say 42) for sizeof(void) and still do
pointer arithmetic by any offset of the compiler implementors choice.
But whoever thought that arithmetic
on void *s was a good idea?

People who have to implement a real world compiler using the host
environment's assembly language. If you look at the list of GCC extensions,
at least a third are due to or for assembly language.


Rod Pemberton
 
J

Jack Klein

Really? As I see it, since sizeof(void) and pointer arithmetic are
undefined by the C standards, the compiler is free to return zero (or as
Brody said 37, or McIntyre would say 42) for sizeof(void) and still do
pointer arithmetic by any offset of the compiler implementors choice.

There's a little more to it. The C standard defines void as an
incomplete type that cannot be completed, and it is a constraint
violation to apply the sizeof operator to an incomplete type.

So while the implementer is entitled to do whatever he/she likes,
since the behavior is undefined, the standard requires a diagnostic.
People who have to implement a real world compiler using the host
environment's assembly language. If you look at the list of GCC extensions,
at least a third are due to or for assembly language.

Which assembly language? x86, PowerPC, MIPS, ARM, etc.?

Give me a break. Attempting to apply sizeof to an incomplete type and
attempting to perform pointer arithmetic on an incomplete type are
errors that completely diagnosable at compile time, hence making them
constraint violations.

This particular extension has more to do with not breaking the code of
lazy and/or ignorant and/or sloppy programmers, than it does with the
assembly language. That statement makes no sense at all.
 
M

Mark McIntyre

Brody said 37, or McIntyre would say 42)

Fame at last.

However FTR, it was the late and much lamented Douglas Adams who said
that.
--
Mark McIntyre

"Debugging is twice as hard as writing the code in the first place.
Therefore, if you write the code as cleverly as possible, you are,
by definition, not smart enough to debug it."
--Brian Kernighan
 
O

Old Wolf

Jack said:
There's a little more to it. The C standard defines void as an
incomplete type that cannot be completed, and it is a constraint
violation to apply the sizeof operator to an incomplete type.

So while the implementer is entitled to do whatever he/she likes,
since the behavior is undefined, the standard requires a diagnostic.

The diagnostic is required because of the constraint violation.

In general, undefined behaviour does not require a diagnostic.
Also, constraint violations may not result in UB, but they still
do require a diagnostic. See C99 5.1.1.3.
 
K

Keith Thompson

Old Wolf said:
The diagnostic is required because of the constraint violation.

In general, undefined behaviour does not require a diagnostic.
Also, constraint violations may not result in UB, but they still
do require a diagnostic. See C99 5.1.1.3.

For some reason, I'm thinking that a constraint violation *does* cause
undefined behavior (if the program is successfully translated after
the required diagnostic), but I can't find a specific reference.

In most cases, the behavior would be undefined by omission.
 
P

Peter Nilsson

Keith said:
For some reason, I'm thinking that a constraint violation *does* cause
undefined behavior (if the program is successfully translated after
the required diagnostic), but I can't find a specific reference.

Mike Wahler had some comments on this...

http://groups.google.com/group/comp.lang.c/msg/3d4422af243a43ce
In most cases, the behavior would be undefined by omission.

This violates a constraint on some implementations, but that
notwithstanding,
it appears to have well defined semantics on any conforming C99
implementation. [Assuming no typos...]

#include <stdio.h>
#include <stdint.h>

int main(void)
{
int a;

#ifdef INTPTR_MAX
void *p = &a;
intptr_t i = p; /* constraint violation */
int *q = (void *) i;
#else
int *q = &a;
#endif

*q = 42;
printf("%d\n", a);
}
 
K

Keith Thompson

Peter Nilsson said:
Keith said:
For some reason, I'm thinking that a constraint violation *does* cause
undefined behavior (if the program is successfully translated after
the required diagnostic), but I can't find a specific reference.

Mike Wahler had some comments on this...

http://groups.google.com/group/comp.lang.c/msg/3d4422af243a43ce
In most cases, the behavior would be undefined by omission.

This violates a constraint on some implementations, but that
notwithstanding,
it appears to have well defined semantics on any conforming C99
implementation. [Assuming no typos...]

#include <stdio.h>
#include <stdint.h>

int main(void)
{
int a;

#ifdef INTPTR_MAX
void *p = &a;
intptr_t i = p; /* constraint violation */
int *q = (void *) i;
#else
int *q = &a;
#endif

*q = 42;
printf("%d\n", a);
}

The marked line is a constraint violation because it uses a pointer
value to initialize an integer object without a cast. For an
initializer of a scalar object, "the same type constraints and
conversions as for simple assignment apply" (C99 6.7.8p11); attempting
to assign a pointer value to an integer object violates the
constraints for simple assignment (C99 6.5.16.1).

A compiler is free to continue processing the translation unit after
issuing a diagnostic for this constraint violation. But you seem to
be assuming that the behavior of
intptr_t i = p;
will be to convert p from void* to intptr_t and assign the result to i.
I see nothing in the standard that supports this assumption.

Unless I'm missing something, the standard doesn't define the behavior
of this construct.

If there's a case where the standard says something is a constraint
violation, but nevertheless defines its behavior if the compiler
chooses to accept it after issuing a diagnostic, I'd be interested in
seeing it.
 
P

Peter Nilsson

Keith said:
Peter Nilsson said:
Keith said:
For some reason, I'm thinking that a constraint violation *does* cause
undefined behavior (if the program is successfully translated after
the required diagnostic), but I can't find a specific reference.

Mike Wahler had some comments on this...

http://groups.google.com/group/comp.lang.c/msg/3d4422af243a43ce
In most cases, the behavior would be undefined by omission.

This violates a constraint on some implementations, but that
notwithstanding, it appears to have well defined semantics on
any conforming C99 implementation. [Assuming no typos...]

#include <stdio.h>
#include <stdint.h>

int main(void)
{
int a;

#ifdef INTPTR_MAX
void *p = &a;
intptr_t i = p; /* constraint violation */
int *q = (void *) i;
#else
int *q = &a;
#endif

*q = 42;
printf("%d\n", a);
}

... A compiler is free to continue processing the translation unit after
issuing a diagnostic for this constraint violation. But you seem to
be assuming that the behavior of
intptr_t i = p;
will be to convert p from void* to intptr_t and assign the result to i.
I see nothing in the standard that supports this assumption.

6.5.16 gives the semantics of assignment.
6.5.16.1p2 says the conversion of p to an intptr_t is implicit in the
assignment.
6.3.2.3p6 says the conversion is allowed, albeit with caveats.
7.18.1.4p1 says the conversion is, in fact, well defined.

Thus, apart from the constraint violation, it's similar to...

unsigned char c = -1L;

An implicit conversion is present and well defined.
 
K

Keith Thompson

Peter Nilsson said:
Keith said:
Peter Nilsson said:
Keith Thompson wrote:
For some reason, I'm thinking that a constraint violation *does* cause
undefined behavior (if the program is successfully translated after
the required diagnostic), but I can't find a specific reference.

Mike Wahler had some comments on this...

http://groups.google.com/group/comp.lang.c/msg/3d4422af243a43ce

In most cases, the behavior would be undefined by omission.

This violates a constraint on some implementations, but that
notwithstanding, it appears to have well defined semantics on
any conforming C99 implementation. [Assuming no typos...]

#include <stdio.h>
#include <stdint.h>

int main(void)
{
int a;

#ifdef INTPTR_MAX
void *p = &a;
intptr_t i = p; /* constraint violation */
int *q = (void *) i;
#else
int *q = &a;
#endif

*q = 42;
printf("%d\n", a);
}

... A compiler is free to continue processing the translation unit after
issuing a diagnostic for this constraint violation. But you seem to
be assuming that the behavior of
intptr_t i = p;
will be to convert p from void* to intptr_t and assign the result to i.
I see nothing in the standard that supports this assumption.

6.5.16 gives the semantics of assignment.
6.5.16.1p2 says the conversion of p to an intptr_t is implicit in the
assignment.
6.3.2.3p6 says the conversion is allowed, albeit with caveats.
7.18.1.4p1 says the conversion is, in fact, well defined.

Thus, apart from the constraint violation, it's similar to...

unsigned char c = -1L;

An implicit conversion is present and well defined.

Interesting.

6.5.16.1p1 lists the constraints on the types of the operands; if one
operand is an integer and the other is a pointer, it violates the
constraints.

6.5.16.1p2 says:

In_simple assignment_ (=), the value of the right operand is
converted to the type of the assignment expression and replaces
the value stored in the object designated by the left operand.

I reluctantly agree with your analysis. I wonder if that was the
intent. I think I'll bring it up in comp.std.c.
 

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
473,768
Messages
2,569,574
Members
45,048
Latest member
verona

Latest Threads

Top