offset of a bit field

P

parag_paul

#include <stdio.h>
#include<stddef.h>

int main(){
typedef struct aptmpl {
int a;
int b;
int c:28,
d:1,
e:1,
f:1,
g:1;
} APTMPL;

printf(" the location si %d\n", offsetof(APTMPL, c));

}


I get the following error

p1.c: In function âmainâ:
p1.c:15: error: attempt to take address of bit-field structure member
âcâ


IS there any way , I can get the offset of a bit field, directly.
( should be portable code)
 
F

Flash Gordon

(e-mail address removed) wrote:

IS there any way , I can get the offset of a bit field, directly.
( should be portable code)

There is no way to do it portably, and no way to do it non-portably that
I am aware of. You need to re-think how to solve your actual problem,
the one you thought finding the address of a bitfield might help with.
 
J

James Kuyper

#include <stdio.h>
#include<stddef.h>

int main(){
typedef struct aptmpl {
int a;
int b;
int c:28,

Note: in ordinary declarations, 'int' is the same as 'signed' int'.
However, when plain 'int' is used as a bit-field type, it's
implementation defined whether the corresponding bit field is signed or
unsigned (6.7.2p5). It is seldom, if ever, a good idea to be unsure
about whether a variable is signed or unsigned, so it's usually best to
explicitly use either 'unsigned' or 'signed' when declaring bit fields.
I will assume, below, that 'c' is signed; by a convenient accident, my
code will do what it's intended to do, even if c is unsigned - but I
wouldn't recommend counting on such accidents.

You mention portability down below. Keep in mind that 'int' can have as
few as 16 bits, in which case int c:28 violates a constraint
(6.7.2.1p2). You can't portably declare a bit field to have any type
larger than int, and therefore you can't portably define a bit field
with more than 16 bits.
d:1,
e:1,
f:1,
g:1;
} APTMPL;

printf(" the location si %d\n", offsetof(APTMPL, c));

}


I get the following error

p1.c: In function âmainâ:
p1.c:15: error: attempt to take address of bit-field structure member
âcâ


IS there any way , I can get the offset of a bit field, directly.
( should be portable code)

No.
And yes, sort of:

struct aptmpl s;
memset(&s, 0, sizeof s); /* clear every bit of every byte of 's' */

s.c = 0x7FFFFFF; /* set every value bit of 'c' */
unsigned char *p = (unsigned char*)&s;
size_t off1, off2;

for(off1=0; off1 < sizeof s && !p[off1]; off1++);

/* You can't assign a single value to c that sets all the value
* bits and the sign bit, without making assumptions about
* whether signed integers use a 2's complement, 1's complement,
* or sign/magnitude representation, all three of which are
* explicitly permitted by the standard. If you're willing to
* assume a particular representation, then only one loop
* would be needed.
*/

s.c = -1; /* set the sign bit of 'c' */
for(off2=0; off1 < sizeof s && !p[off2]; off2++);

/* there's no guarantee that the sign bit is stored in the first
* byte, or in the last one (or indeed, anywhere else
* in between).
*/
if(off2 < off1)
off1 = off2;

At this point, off1 identifies the offset of the first byte in 's' whose
value was affected by setting any of the sign or value bits of 's.c'. On
systems where int is a type with more than 32 bits, this might be a byte
containing only padding bits. This might be a byte containing bits from
'c', but also bits that represent d, e, f, or g. With those issues in
mind, what in the world do you want to do with it?

I strongly suspect that you don't have a reason for wanting to know this
number, that makes sense for code that's intended to be portable.
 
K

Keith Thompson

#include <stdio.h>
#include<stddef.h>

int main(){
typedef struct aptmpl {
int a;
int b;
int c:28,
d:1,
e:1,
f:1,
g:1;
} APTMPL;

printf(" the location si %d\n", offsetof(APTMPL, c));

}


I get the following error

p1.c: In function âmainâ:
p1.c:15: error: attempt to take address of bit-field structure member
âcâ


IS there any way , I can get the offset of a bit field, directly.
( should be portable code)

What would you do with it if you could get it? I can't think of any
portable use for it.
 
B

BartC

Gordon Burditt said:
You can't take the address of a bit field. What does "offset of a
bit field" even MEAN?

It could mean a char offset plus a bit offset (eg 24:2), or a fractional
offset (24 3/8), or an offset plus a mask (24:100B for a single bit).

In fact it can be well defined.

It's just not easy in C, given an arbitrary struct name and the name of a
bitfield within it, to obtain this value.
 
K

Keith Thompson

You can't take the address of a bit field. What does "offset of a
bit field" even MEAN? The normal definition of "offset" doesn't
apply here. Is it anything like "take the smell and telephone
number of the bit field and take the geometric mean of the two"?

Since there's no definition of "offset of a bit field", there's no
way to get it, portably or un-portably.

Sure, but you can meaningfully talk about which bits within a
structure are occupied by a given bit field. The standard even talks
about the "addressible storage unit" that contains a bit field (C99
6.7.2.1).

For example, given:

struct {
unsigned int x:2;
unsigned int y:6;
unsigned int z:8;
};

you might have x occupying bits 0-1 of byte 0, y occupying bytes 2-7
of byte 1, and z occupying buts 0-7 of byte 2. (The numbers are just
examples.) And I've worked on a software system that extracted that
kind of information (and would have made good use of it if I'd been
able to finish it.)

You're right that the language doesn't support offsets for bit fields,
and the concept would be difficult to define because bit fields don't
necessarily occupy full bytes, but the idea isn't nearly as
nonsensical as taking the smell or telephone number of a bit field.
 
R

Richard Tobin

You can't take the address of a bit field. What does "offset of a
bit field" even MEAN?
[/QUOTE]
It could mean a char offset plus a bit offset (eg 24:2), or a fractional
offset (24 3/8), or an offset plus a mask (24:100B for a single bit).

It *could* mean they, but there'd be no point unless there was
something you can do with such offsets.

Since addresses can only point to bytes, there's no point having
offsets be any finer-grained.

-- Richard
 
C

CBFalconer

#include <stdio.h>
#include<stddef.h>

int main(){
typedef struct aptmpl {
int a;
int b;
int c:28,
d:1,
e:1,
f:1,
g:1;
} APTMPL;

printf(" the location si %d\n", offsetof(APTMPL, c));
.... snip ...

IS there any way , I can get the offset of a bit field,
directly. (should be portable code)

No. See the C standard:

6.7.2.1 Structure and union specifiers

.... snip ...

[#7] A member of a structure or union may have any object
type other than a variably modified type.93) In addition, a
member may be declared to consist of a specified number of
bits (including a sign bit, if any). Such a member is
called a bit-field;94) its width is preceded by a colon.

.... snip ...

94)The unary & (address-of) operator cannot be applied to a
bit-field object; thus, there are no pointers to or
arrays of bit-field objects.
 
K

Keith Thompson

CBFalconer said:
#include <stdio.h>
#include<stddef.h>

int main(){
typedef struct aptmpl {
int a;
int b;
int c:28,
d:1,
e:1,
f:1,
g:1;
} APTMPL;

printf(" the location si %d\n", offsetof(APTMPL, c));
... snip ...

IS there any way , I can get the offset of a bit field,
directly. (should be portable code)
No.

Correct.

See the C standard:

6.7.2.1 Structure and union specifiers

... snip ...

[#7] A member of a structure or union may have any object
type other than a variably modified type.93) In addition, a
member may be declared to consist of a specified number of
bits (including a sign bit, if any). Such a member is
called a bit-field;94) its width is preceded by a colon.

... snip ...

94)The unary & (address-of) operator cannot be applied to a
bit-field object; thus, there are no pointers to or
arrays of bit-field objects.

Since he didn't attempt to apply the unary "&" operator to a
bit-field, it's difficult to see how that's relevant unless you also
look at the description of the offsetof macro in 7.17p3, which
specifically says that "If the specified member is a bit-field, the
behavior is undefined."

But even that doesn't entirely answer the question. The OP already
knows that offsetof won't work. Explaining why can be useful, but
that doesn't exclude the possibility that there might be another way
to do it. (As it happens, there isn't.)
 
C

CBFalconer

Richard said:
Richard Tobin said:



Any statement that sweeping /must/ be wrong. Offhand, however, I
can't quite demonstrate how it's wrong, so you're going to have
to take my word for it.

I won't. Mr Tobin is quite correct.
 
K

Keith Thompson

CBFalconer said:
I won't. Mr Tobin is quite correct.

Really? No point at all?

Suppose you have a library (implemented in standard C, of course) that
lets you deal with bit fields. For example there might be a function

unsigned int bf_fetch(void *base, size_t bit_offset, size_t bits);

that returns the value of a bit-field starting at the specified base
address, at the specified offset in bits, of the specified size. So
bf_fetch(0, 0, CHAR_BIT), for example, would fetch a single byte from
the specified address. And there would be a corresponding function
that would store a value. With bits==1, this gives you bit arrays.

If you could determine the offset in bits of a specified bit field,
you could use this library to manipulate it (with some system-specific
assumptions about how bit fields are laid out). You could build a
table containing the name, offset, and size of each bit-field in a
given structure, and use the interface to, for example, fetch values
by name, or traverse a structure using a loop rather than by accessing
each member individually.
 
B

Bart

It *could* mean they, but there'd be no point unless there was
something you can do with such offsets.

Since addresses can only point to bytes, there's no point having
offsets be any finer-grained.

It's not possible for C to have char-addressing on machines which only
have word-addressing at the hardware level? (I'm thinking of pdp10 and
probably loads more)

If so, addresses could also have extra information to isolate specific
bits.

Even if not directly possible in C, it would be possible at the user
level.

I've worked on languages which have pointers to bits and bitfields,
and it's not a big deal. It just that C doesn't have them built-in to
the language.
 
J

James Kuyper

It could mean a char offset plus a bit offset (eg 24:2), or a fractional
offset (24 3/8), or an offset plus a mask (24:100B for a single bit).

It *could* mean they, but there'd be no point unless there was
something you can do with such offsets.

Since addresses can only point to bytes, there's no point having
offsets be any finer-grained.[/QUOTE]

The combination of an address and a bit offset could be used to point to
bit-field. It's just not something that C allows you to do, at least not
in any portable fashion, but there's nothing inherently impossible about
it. Some implementations implement a char* pointer by combining a word
address and a byte offset; since they choose to make the byte size
smaller than the word size. Pointers that could point at individual bits
would be only a little more complicated than that.
 
R

Richard Tobin

Since addresses can only point to bytes, there's no point having
offsets be any finer-grained.
[/QUOTE]
The combination of an address and a bit offset could be used to point to
bit-field. It's just not something that C allows you to do, at least not
in any portable fashion, but there's nothing inherently impossible about
it. Some implementations implement a char* pointer by combining a word
address and a byte offset; since they choose to make the byte size
smaller than the word size. Pointers that could point at individual bits
would be only a little more complicated than that.

Ok, I could have hedged my comment about a bit to make it more
undisputably true. But offsetof() is clearly intended to be used
with ordinary pointers; if you ask why it can't be applied to
bit-fields you might as well ask why & can't be applied to them,
and why you can't add 1/CHAR_BIT to a pointer.

[Don't bother pointing out that you can in fact add 1/CHAR_BIT to any pointer.]

-- Richard
 
J

James Kuyper

The combination of an address and a bit offset could be used to point to
bit-field. It's just not something that C allows you to do, at least not
in any portable fashion, but there's nothing inherently impossible about
it. Some implementations implement a char* pointer by combining a word
address and a byte offset; since they choose to make the byte size
smaller than the word size. Pointers that could point at individual bits
would be only a little more complicated than that.

Ok, I could have hedged my comment about a bit to make it more
undisputably true. But offsetof() is clearly intended to be used
with ordinary pointers; if you ask why it can't be applied to
bit-fields you might as well ask why & can't be applied to them,[/QUOTE]


But the question was not why offsetof() couldn't be applied. The
question was whether there was an alternative - which led to the
question of whether it was even meaningful to talk about the offset of a
bit-field. I believe that it is; but given the amount of freedom the
standard gives to implementors in laying out bit-fields, there's little
or nothing useful that can be done with the information.
 
G

Guest

#include <stdio.h>
#include<stddef.h>
int main(){
typedef struct aptmpl {
int a;
int b;
int c:28,
} APTMPL;
printf(" the location si %d\n", offsetof(APTMPL, c));
}
I get the following error
p1.c: In function âmainâ:
p1.c:15: error: attempt to take address of bit-field structure member
âcâ
IS there any way , I can get the offset of a bit field, directly.
( should be portable code)

No.
And yes, sort of:

     struct aptmpl s;
     memset(&s, 0, sizeof s); /* clear every bit of every byte of 's' */

     s.c = 0x7FFFFFF; /* set every value bit of 'c' */
     unsigned char *p = (unsigned char*)&s;
     size_t off1, off2;

     for(off1=0; off1 < sizeof s && !p[off1]; off1++);

     /* You can't assign a single value to c that sets all the value
      * bits and the sign bit, without making assumptions about
      * whether signed integers use a 2's complement, 1's complement,
      * or sign/magnitude representation, all three of which are
      * explicitly permitted by the  standard. If you're willing to
      * assume a particular representation, then only one loop
      * would be needed.
      */

     s.c = -1; /* set the sign bit of 'c' */
     for(off2=0; off1 < sizeof s && !p[off2]; off2++);

     /* there's no guarantee that the sign bit is stored in the first
      * byte, or in the last one (or indeed, anywhere else
      * in between).
      */
     if(off2 < off1)
         off1 = off2;

At this point, off1 identifies the offset of the first byte in 's' whose
value was affected by setting any of the sign or value bits of 's.c'. On
systems where int is a type with more than 32 bits, this might be a byte
containing only padding bits. This might be a byte containing bits from
'c', but also bits that represent d, e, f, or g. With those issues in
mind, what in the world do you want to do with it?

I strongly suspect that you don't have a reason for wanting to know this
number, that makes sense for code that's intended to be portable.- Hide quoted text -

I suppose you might know how bits were laid out in a byte
(eg. hardware) and want to access them using bitfields.
Seems like the wrong way to go about it though. He'd be
better linking in different versions of the code on different
platforms. Or even better using &,| etc.
 
C

CBFalconer

.... snip ...

I suppose you might know how bits were laid out in a byte (eg.
hardware) and want to access them using bitfields. Seems like
the wrong way to go about it though. He'd be better linking in
different versions of the code on different platforms. Or even
better using &,| etc.

Especially since there are no (i.e. zip) guarantees about how the
bits in bitfields are selected. Use constants and | or &.
 
C

CBFalconer

Keith said:
Really? No point at all?

Suppose you have a library (implemented in standard C, of course) that
lets you deal with bit fields. For example there might be a function

unsigned int bf_fetch(void *base, size_t bit_offset, size_t bits);

that returns the value of a bit-field starting at the specified base
address, at the specified offset in bits, of the specified size. So
bf_fetch(0, 0, CHAR_BIT), for example, would fetch a single byte from
the specified address. And there would be a corresponding function
that would store a value. With bits==1, this gives you bit arrays.

If you could determine the offset in bits of a specified bit field,
you could use this library to manipulate it (with some system-specific
assumptions about how bit fields are laid out). You could build a
table containing the name, offset, and size of each bit-field in a
given structure, and use the interface to, for example, fetch values
by name, or traverse a structure using a loop rather than by accessing
each member individually.

Nothing wrong with your argument. But addresses (see first quote)
are the things that are stored in pointers, and may be the whole
content. Now if you want a bit address you really need a
structure:

struct baddress {
size_t sz;
size_t bit_offset;
void *base;
} baddress;

and now you can use, pass, etc. this.
 
C

CBFalconer

Richard said:
.... snip ...

[Don't bother pointing out that you can in fact add 1/CHAR_BIT
to any pointer.]

In fact you can add n/CHAR_BIT to any pointer, for any positive
value of n < 8. :)
 
B

Ben Bacarisse

CBFalconer said:
Especially since there are no (i.e. zip) guarantees about how the
bits in bitfields are selected.

That is not true. The standard does not say much about it but it does
give some guarantees both about how consecutive bit-fields should be
handled and about how bit-field and non-bit-field members get
allocated. It is not much, but it is more than zip.
 

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,770
Messages
2,569,584
Members
45,075
Latest member
MakersCBDBloodSupport

Latest Threads

Top