&errno, sizeof errno

V

viza

Hi all,
A quick one - since errno is a lvalue, can I do:

fread( & errno, sizeof errno, 1, fp )

?
TIA
viza
 
H

Harald van Dijk

Ahh, a challange... What if an implementation did something like:

struct {
__flags : 16;
} __errrno;

#define errno (__errno.__flags)

/* :) */

If the implementation does that, I would argue that the type of errno is
not int (even if int has 16 bits). Instead, the type is int : 16. Another
possibility is
extern volatile int errno;
where I would argue the type is volatile int.

However, consider this:

register int errno;

Even though user code is not permitted to define static objects with the
keyword register, if this is a supported extension by the implementation,
I don't think any requirements on errno have been violated if the
implementation makes use of it.
 
V

viza

Ahh, a challange... What if an implementation did something like:

struct {
__flags : 16;
} __errrno;

#define errno (__errno.__flags)

__errno.__flags is not a "modifiable lvalue of type int".

Ok, I forgot that the implementation of fread() might write an
intermediate error to errno even in the case of ultimate success.
 
J

James Kuyper

Harald said:
If the implementation does that, I would argue that the type of errno is
not int (even if int has 16 bits). Instead, the type is int : 16.

A bit-field's width is not part of the type of the bit-field. It merely
determines how much space that bit field takes up. See 6.3.1.1p2, which
says:

"The following may be used in an expression wherever an int or unsigned
int may be used:
....
— A bit-field of type _Bool, int, signed int, or unsigned int."

If the width of a bit-field were part of it's type, the parenthesized
part of 6.3.2.3p5 would be unnecessary: "Two structures share a common
initial sequence if corresponding members have compatible types (and,
for bit-fields, the same widths)".

6.7.2p5 says "Each of the comma-separated sets designates the same type,
except that for bit-fields, it is implementation-defined whether the
specifier int designates the same type as signed int or the same type
as unsigned int."

6.7.2.1p4: "A bit-field shall have a type that is a qualified or
unqualified version of _Bool, signed int, unsigned int, or some other
implementation-defined type."

In each case, the standard talks about the type of a bit field without
while referring only to standard-defined type names, and not referring
to the width.
 
H

Harald van Dijk

Harald said:
If the implementation does that, I would argue that the type of errno
is not int (even if int has 16 bits). Instead, the type is int : 16.

A bit-field's width is not part of the type of the bit-field. It merely
determines how much space that bit field takes up. [examples snipped]

In each case, the standard talks about the type of a bit field without
while referring only to standard-defined type names, and not referring
to the width.

It's interesting that one of the examples you gave was 6.3.1.1p2. I'll
quote another part of it:

"If an int can represent all values of the original type, the value is
converted to an int; otherwise, it is converted to an unsigned int. These
are called the integer promotions."

Here, "the original type" does include the bit field's width. The standard
is not consistent in treating width as part of the type.
 
K

Keith Thompson

James Kuyper said:
A bit-field's width is not part of the type of the bit-field. It
merely determines how much space that bit field takes up. See
6.3.1.1p2, which says:

"The following may be used in an expression wherever an int or
unsigned int may be used:
...
Ñ A bit-field of type _Bool, int, signed int, or unsigned int." [...]
6.7.2.1p4: "A bit-field shall have a type that is a qualified or
unqualified version of _Bool, signed int, unsigned int, or some other
implementation-defined type."

In each case, the standard talks about the type of a bit field without
while referring only to standard-defined type names, and not referring
to the width.

Agreed. But 6.7.2.1p9 confuses matters slightly:

A bit-field is interpreted as a signed or unsigned integer type
consisting of the specified number of bits.

So, apparently, given:

struct {
unsigned int bf:3;
};

bf *is* of type unsigned int (at least 16 bits), but it's *interpreted
as* an unsigned integer type consisting of 3 bits.

(Though the standard says it's interpreted as a type, it's actually
interpreted as a member of that type.)
 
K

Keith Thompson

Harald van Dijk said:
Harald said:
If the implementation does that, I would argue that the type of errno
is not int (even if int has 16 bits). Instead, the type is int : 16.

A bit-field's width is not part of the type of the bit-field. It merely
determines how much space that bit field takes up. [examples snipped]

In each case, the standard talks about the type of a bit field without
while referring only to standard-defined type names, and not referring
to the width.

It's interesting that one of the examples you gave was 6.3.1.1p2. I'll
quote another part of it:

"If an int can represent all values of the original type, the value is
converted to an int; otherwise, it is converted to an unsigned int. These
are called the integer promotions."

Here, "the original type" does include the bit field's width.

I don't believe it does.

Here's the context (I'm quoting from n1256, which does differ from
C99; I haven't gone back to check what the change bar refers to):

The following may be used in an expression wherever an int or
unsigned int may be used:

-- An object or expression with an integer type whose integer
conversion rank is less than or equal to the rank of int and
unsigned int. [n1256 has a change bar here]

-- A bit-field of type _Bool, int, signed int, or unsigned int.

If an int can represent all values of the original type, the value
is converted to an int; otherwise, it is converted to an unsigned
int. These are called the _integer promotions_. All other types
are unchanged by the integer promotions.

As far as I can tell, given a bit field "unsigned int bf:3;", the
"original type" of bf is unsigned int.

This does make a difference. If the "original type" is "unsigned
int:3", then the value would be promoted to type int; if the original
type is unsigned int, then the value would be (trivially) promoted to
type unsigned int. But I can't think of a case where the difference
would be visible in the behavior of a program.
The standard
is not consistent in treating width as part of the type.

It's not as clear as it might be, but I *think* it's consistent.
 
H

Harald van Dijk

Harald van Dijk said:
It's interesting that one of the examples you gave was 6.3.1.1p2. I'll
quote another part of it:

"If an int can represent all values of the original type, the value is
converted to an int; otherwise, it is converted to an unsigned int.
These are called the integer promotions."

Here, "the original type" does include the bit field's width.

I don't believe it does.
[...]
As far as I can tell, given a bit field "unsigned int bf:3;", the
"original type" of bf is unsigned int.

I picked that sentence so that I could avoid a lengthy discussion in case
of a disagreement. See DR #122. :)
 
K

Keith Thompson

Harald van Dijk said:
Harald van Dijk said:
It's interesting that one of the examples you gave was 6.3.1.1p2. I'll
quote another part of it:

"If an int can represent all values of the original type, the value is
converted to an int; otherwise, it is converted to an unsigned int.
These are called the integer promotions."

Here, "the original type" does include the bit field's width.

I don't believe it does.
[...]
As far as I can tell, given a bit field "unsigned int bf:3;", the
"original type" of bf is unsigned int.

I picked that sentence so that I could avoid a lengthy discussion in case
of a disagreement. See DR #122. :)

But DR #122 applies to C90 (which I'm guessing is the reason for the
smiley).
 
H

Harald van Dijk

Harald van Dijk said:
It's interesting that one of the examples you gave was 6.3.1.1p2.
I'll quote another part of it:

"If an int can represent all values of the original type, the value
is
converted to an int; otherwise, it is converted to an unsigned int.
These are called the integer promotions."

Here, "the original type" does include the bit field's width.

I don't believe it does.
[...]
As far as I can tell, given a bit field "unsigned int bf:3;", the
"original type" of bf is unsigned int.

I picked that sentence so that I could avoid a lengthy discussion in
case of a disagreement. See DR #122. :)

But DR #122 applies to C90

Sure, but the text is unchanged between C90 and C99, so I see no reason
for assuming there is a difference in meaning, and I am not aware of C99-
conforming compilers following a different interpretation.
(which I'm guessing is the reason for the smiley).

The smiley was because I figured it would be hard to find any other
example more explicit than that.
 
K

Keith Thompson

Harald van Dijk said:
Harald van Dijk said:
On Fri, 12 Sep 2008 15:32:50 -0700, Keith Thompson wrote:
It's interesting that one of the examples you gave was 6.3.1.1p2.
I'll quote another part of it:

"If an int can represent all values of the original type, the value
is
converted to an int; otherwise, it is converted to an unsigned int.
These are called the integer promotions."

Here, "the original type" does include the bit field's width.

I don't believe it does.
[...]
As far as I can tell, given a bit field "unsigned int bf:3;", the
"original type" of bf is unsigned int.

I picked that sentence so that I could avoid a lengthy discussion in
case of a disagreement. See DR #122. :)

But DR #122 applies to C90

Sure, but the text is unchanged between C90 and C99, so I see no reason
for assuming there is a difference in meaning, and I am not aware of C99-
conforming compilers following a different interpretation.
(which I'm guessing is the reason for the smiley).

The smiley was because I figured it would be hard to find any other
example more explicit than that.

If that was the intent, it's a pity they didn't change the wording in
C99 to reflect that.
 
T

Tim Rentsch

viza said:
__errno.__flags is not a "modifiable lvalue of type int".

If in some implementation ints are 32 bits, and if we have

struct { int __flags : 32; } __errno;

then how is the type of (__errno.__flags) different from int?
Certainly (__errno.__flags) is a modifiable lvalue.

I understand its address cannot be taken with &, but that's
because it's a bitfield, not because of its type.
 
V

vippstar

If in some implementation ints are 32 bits, and if we have

struct { int __flags : 32; } __errno;

then how is the type of (__errno.__flags) different from int?
Certainly (__errno.__flags) is a modifiable lvalue.

I understand its address cannot be taken with &, but that's
because it's a bitfield, not because of its type.


Another point: If its type were a bitfield int of 32 bits, then a cast
would make sense;
However, (int : 16) is a syntax error.
 
T

Tim Rentsch

James Kuyper said:
A bit-field's width is not part of the type of the bit-field. It merely
determines how much space that bit field takes up.

The width of a bit-field does affect its type when the
bit-field member is used in an expression.

struct { unsigned bf : 8; } s;
s.bf = 0;
printf( "s.bf - 1 < 1 == %d\n", s.bf - 1 < 1 );

Changing '8' to the number of bits in an unsigned int
will result in a different value.
 
T

Tim Rentsch

Tim Rentsch said:
If in some implementation ints are 32 bits, and if we have

struct { int __flags : 32; } __errno;

then how is the type of (__errno.__flags) different from int?
Certainly (__errno.__flags) is a modifiable lvalue.

I understand its address cannot be taken with &, but that's
because it's a bitfield, not because of its type.

Of course, I meant to say 'signed int' rather than 'int' there...
 
T

Tim Rentsch

Another point: If its type were a bitfield int of 32 bits, then a cast
would make sense;
However, (int : 16) is a syntax error.

You do realize don't you that this point is irrelevant to the
question that was asked?
 
V

vippstar

^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
You do realize don't you that this point is irrelevant to the
question that was asked?


Actually, no, not really. I was trying to make a point why
__errno.__flags' type is int.
I replied to the question marked with '^', I thought you did the same.
 

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

Similar Threads


Members online

Forum statistics

Threads
473,731
Messages
2,569,432
Members
44,832
Latest member
GlennSmall

Latest Threads

Top