Printing the bitfields

K

karthikbalaguru

Hi,

I have a query related to the printing of bit fields .

Code Set - 1
===========
#include<stdio.h>
int main(void)
{
struct dummy
{
unsigned int a : 1;
unsigned int b : 1;
unsigned int c : 1;
unsigned int d : 1;
unsigned int e : 1;
unsigned int f : 1;
unsigned int g : 1;
unsigned int h : 1;
};
struct dummy d1;
d1.a = 1;
d1.b = 1;
d1.c = 1;
d1.d = 1;
d1.e = 1;
d1.f = 1;
d1.g = 1;
d1.h = 1;
printf("%x \n",d1);
return 0;
}

For the above code, i got the output as :-
ccccccff

I was wondering of the occurance of C's
even after repeated execution and changed
the struct definition as below -
static struct dummy d1;

After the above change, i got the output
as ff .

Later,
I tried to change the code as below to check
with other datatypes for bit fields.

Code Set - 2
=============
#include<stdio.h>
int main(void)
{
struct dummy
{
char a : 1;
char b : 1;
char c : 1;
char d : 1;
char e : 1;
char f : 1;
char g : 1;
unsigned int h : 1;
};
static struct dummy d1;
d1.a = 1;
d1.b = 1;
d1.c = 1;
d1.d = 1;
d1.e = 1;
d1.f = 1;
d1.g = 1;
d1.h = 1;
printf("%x \n",d1);
return 0;
}

But, i got the output as 7f instead
of ff that i got for the 'Code Set - 1' ?

I do not have any bit fields as zero
in the 'Code Set - 2', But, how
did it gives the ouput as 7f ?

Further, can we use any kind of
datatype for declaring and using of
bit fields in a structure ?

Thx in advans,
Karthik Balaguru
 
B

Ben Bacarisse

karthikbalaguru said:
I have a query related to the printing of bit fields .

Code Set - 1
===========
#include<stdio.h>
int main(void)
{
struct dummy
{
unsigned int a : 1;
unsigned int b : 1;
unsigned int c : 1;
unsigned int d : 1;
unsigned int e : 1;
unsigned int f : 1;
unsigned int g : 1;
unsigned int h : 1;
};
struct dummy d1;
d1.a = 1;
d1.b = 1;
d1.c = 1;
d1.d = 1;
d1.e = 1;
d1.f = 1;
d1.g = 1;
d1.h = 1;
printf("%x \n",d1);

This is undefined. If you want to see what re-interpreting one set of
bits as some other type, use a union. The result will be non-portable
and could be undefined if a trap representation is involved, but at
least you can talk about such a program. The implementation can do
almost anything with the above.
return 0;
}

For the above code, i got the output as :-
ccccccff

I was wondering of the occurance of C's
even after repeated execution and changed
the struct definition as below -
static struct dummy d1;

After the above change, i got the output
as ff .

Statics are initialised to zero (by default) so it is likely that you
will see zeros in the unused parts of the struct. I say likely
(rather than certain) because anything is permitted since the code is
undefined (by the C standard).
Later,
I tried to change the code as below to check
with other datatypes for bit fields.

Code Set - 2
=============
#include<stdio.h>
int main(void)
{
struct dummy
{
char a : 1;
char b : 1;
char c : 1;
char d : 1;
char e : 1;
char f : 1;
char g : 1;

char is not a standard bit type. By this I mean that if it works at
all it does so because your implementation permits this as an
extension.
unsigned int h : 1;
};
static struct dummy d1;
d1.a = 1;
d1.b = 1;
d1.c = 1;
d1.d = 1;
d1.e = 1;
d1.f = 1;
d1.g = 1;
d1.h = 1;
printf("%x \n",d1);

Again, undefined.
return 0;
}

But, i got the output as 7f instead
of ff that i got for the 'Code Set - 1' ?

Well, formally, you must consult you implementation's documentation to
see what it does with bit fields that are declared char. For example,
a char bit field might be considered as signed and assigning 1 to a
signed bit field of width 1 might cause an overflow!
I do not have any bit fields as zero
in the 'Code Set - 2', But, how
did it gives the ouput as 7f ?

It is impossible to say. The C standard does not define the meaning
of your program.
Further, can we use any kind of
datatype for declaring and using of
bit fields in a structure ?

No. You should stick to _Bool, signed int and unsigned int.
 
J

James Kuyper

karthikbalaguru said:
Hi,

I have a query related to the printing of bit fields .

Code Set - 1
===========
#include<stdio.h>
int main(void)
{
struct dummy
{
unsigned int a : 1;
unsigned int b : 1;
unsigned int c : 1;
unsigned int d : 1;
unsigned int e : 1;
unsigned int f : 1;
unsigned int g : 1;
unsigned int h : 1;
};
struct dummy d1;
d1.a = 1;
d1.b = 1;
d1.c = 1;
d1.d = 1;
d1.e = 1;
d1.f = 1;
d1.g = 1;
d1.h = 1;
printf("%x \n",d1);
return 0;
}

For the above code, i got the output as :-
ccccccff

What output were you expecting? The behavior of the above code is
undefined, since you told printf() that you were giving it an unsigned
int, whereas in fact you were giving it a struct dummy. Therefore, it
would have been entirely legal for the compiler to generate code which
produces output saying "Stop worrying about what happens when you write
code with undefined behavior!".

Some compilers will warn you of this kind of mistake, if you turn the
warning levels high enough.

....
Later,
I tried to change the code as below to check
with other datatypes for bit fields.

Code Set - 2
=============
#include<stdio.h>
int main(void)
{
struct dummy
{
char a : 1;
char b : 1;
char c : 1;
char d : 1;
char e : 1;
char f : 1;
char g : 1;
unsigned int h : 1;
};
static struct dummy d1;
d1.a = 1;
d1.b = 1;
d1.c = 1;
d1.d = 1;
d1.e = 1;
d1.f = 1;
d1.g = 1;
d1.h = 1;
printf("%x \n",d1);
return 0;
}

But, i got the output as 7f instead
of ff that i got for the 'Code Set - 1' ?

I do not have any bit fields as zero
in the 'Code Set - 2', But, how
did it gives the ouput as 7f ?

Why shouldn't it? The behavior is still undefined, for the same exact
reasons, so 7f is just as legal an output for this program as "Just stop
writing code with undefined behavior.".
Further, can we use any kind of
datatype for declaring and using of
bit fields in a structure ?

The only types that you can portably rely upon being able to use for bit
fields are qualified or unqualified versions of _Bool, signed int, or
unsigned int. Implementations are permitted to define additional types
that can be used for bit-fields, but you cannot make portable use of
that fact.

Note: it is implementation-defined whether a bit field of type 'int', is
signed or unsigned. This is different from the way 'int' works outside
of bit-field declarations.
 
E

Eric Sosman

karthikbalaguru said:
Hi,

I have a query related to the printing of bit fields .

Code Set - 1
===========
#include<stdio.h>
int main(void)
{
struct dummy
{
unsigned int a : 1;
unsigned int b : 1;
unsigned int c : 1;
unsigned int d : 1;
unsigned int e : 1;
unsigned int f : 1;
unsigned int g : 1;
unsigned int h : 1;
};
struct dummy d1;
d1.a = 1;
d1.b = 1;
d1.c = 1;
d1.d = 1;
d1.e = 1;
d1.f = 1;
d1.g = 1;
d1.h = 1;
printf("%x \n",d1);
[...]

Question: What kind of value does "%x" convert? Answer:
An unsigned int.

Question: Is the value of d1 an unsigned int? Answer: No.

Question: What happens when the argument corresponding
to a conversion specifier does not have the required type?
Answer: (Left as an exercise. Hint: Does "U.B." ring a bell?)
Further, can we use any kind of
datatype for declaring and using of
bit fields in a structure ?

Yes, but only int, signed int, unsigned int, and (for
C99 compilers) _Bool are guaranteed to work.
 
K

Keith Thompson

Ben Bacarisse said:
No. You should stick to _Bool, signed int and unsigned int.

Agreed. To expand on that a bit: you *can* also use plain int,
but plain int in a bit field declaration (and only in a bit field
declaration) may be treated as either signed int or unsigned int.
Don't declare a plain int bit field unless you don't care whether
it's treated as signed or unsigned (and you should usually care).

Of course _Bool (or, if you have "#include <stdbool.h>", bool) is
new in C99, and your compiler may or may not support it.
 
K

karthikbalaguru

Agreed.  To expand on that a bit: you *can* also use plain int,
but plain int in a bit field declaration (and only in a bit field
declaration) may be treated as either signed int or unsigned int.
Don't declare a plain int bit field unless you don't care whether
it's treated as signed or unsigned (and you should usually care).

Of course _Bool (or, if you have "#include <stdbool.h>", bool) is
new in C99, and your compiler may or may not support it.

Ok.

Is there a trick to print all the bit fields in the "Code Set - 1"
by using a single format specifier ?
Or
Is the below method of printing is the only way for printing all
the bit fields for that "Code Set - 1"?
printf(" d1.a - %d,d1.b - %d,d1.c - %d,d1.d - %d,d1.e - %d,d1.f -
%d,d1.g - %d,d1.h - %d\n",d1.a,d1.b,d1.c,d1.d,d1.e,d1.f,d1.g,d1.h);

Thx in advans,
Karthik Balaguru
 
L

luser-ex-troll

Ok.

Is there a trick to print all the bit fields in the "Code Set - 1"
by using a single format specifier ?
Or
Is the below method of printing is the only way for printing all
the bit fields for that "Code Set - 1"?
printf(" d1.a - %d,d1.b - %d,d1.c - %d,d1.d - %d,d1.e - %d,d1.f -
%d,d1.g - %d,d1.h - %d\n",d1.a,d1.b,d1.c,d1.d,d1.e,d1.f,d1.g,d1.h);

Thx in advans,
Karthik Balaguru

#include<stdio.h>
int main(void)
{
union dumdum {
unsigned char all_of_it;
struct {
unsigned int a : 1;
unsigned int b : 1;
unsigned int c : 1;
unsigned int d : 1;
unsigned int e : 1;
unsigned int f : 1;
unsigned int g : 1;
unsigned int h : 1;
} dummy;
};
union dumdum d1;
d1.dummy.a = 1;
d1.dummy.b = 1;
d1.dummy.c = 1;
d1.dummy.d = 1;
d1.dummy.e = 1;
d1.dummy.f = 1;
d1.dummy.g = 1;
d1.dummy.h = 1;
printf("d1.dummy.a is %x\n", (int)(d1.dummy.a == 1));
printf("d1.dummy.b is %x\n", (int)(d1.dummy.b == 1));
printf("d1.dummy.c is %x\n", (int)(d1.dummy.c == 1));
printf("d1.dummy.d is %x\n", (int)(d1.dummy.d == 1));
printf("d1.dummy.e is %x\n", (int)(d1.dummy.e == 1));
printf("d1.dummy.f is %x\n", (int)(d1.dummy.f == 1));
printf("d1.dummy.g is %x\n", (int)(d1.dummy.g == 1));
printf("d1.dummy.h is %x\n", (int)(d1.dummy.h == 1));
printf("which are all little slices of %x\n", (int)d1.all_of_it);
return 0;
}
 
B

Ben Bacarisse

luser-ex-troll said:
On Mar 17, 6:43 pm, karthikbalaguru <[email protected]>
wrote:

It is best to snip sigs.
#include<stdio.h>
int main(void)
{
union dumdum {
unsigned char all_of_it;

This char need not "overlap" any of the bit fields if sizeof(struct
dummy) > 1.
struct {
unsigned int a : 1;
unsigned int b : 1;
unsigned int c : 1;
unsigned int d : 1;
unsigned int e : 1;
unsigned int f : 1;
unsigned int g : 1;
unsigned int h : 1;
} dummy;
};

I think is it better to use an array of unsigned char whose size is
sizeof(struct dummy). You can to this by using memcpy and then you
can dispense with the union.

This is general advice: to investigate the representation of a C
object, treat it as an array of unsigned char.
 
B

Barry Schwarz

Ok.

Is there a trick to print all the bit fields in the "Code Set - 1"
by using a single format specifier ?

What part of Ben's advice to use a union doesn't satisfy your intent?
Or
Is the below method of printing is the only way for printing all
the bit fields for that "Code Set - 1"?
printf(" d1.a - %d,d1.b - %d,d1.c - %d,d1.d - %d,d1.e - %d,d1.f -
%d,d1.g - %d,d1.h - %d\n",d1.a,d1.b,d1.c,d1.d,d1.e,d1.f,d1.g,d1.h);

Probably not but you need to be a lot more specific. Does
printf("d1.a-d1.h = %lx\n", (unsigned long)d1.a +
(unsigned long)d1.b<<4 +
(unsigned long)d1.c<<8 +
(unsigned long)d1.d<<12 +
(unsigned long)d1.e<<16 +
(unsigned long)d1.f<<20 +
(unsigned long)d1.g<<24 +
(unsigned long)d1.h<<28);
do what you want?

You really seem to have the emphasis on the wrong syllable.
 
K

karthikbalaguru

[...]
Further, can we use any kind of
datatype for declaring and using of
bit fields in a structure ?
No. You should stick to _Bool, signed int and unsigned int.
Agreed. To expand on that a bit: you *can* also use plain int,
but plain int in a bit field declaration (and only in a bit field
declaration) may be treated as either signed int or unsigned int.
Don't declare a plain int bit field unless you don't care whether
it's treated as signed or unsigned (and you should usually care).
Of course _Bool (or, if you have "#include <stdbool.h>", bool) is
new in C99, and your compiler may or may not support it.

Is there a trick to print all the bit fields in the "Code Set - 1"
by using a single format specifier ?
Or
Is the below method of printing is the only way for printing all
the bit fields for that "Code Set - 1"?
printf(" d1.a - %d,d1.b - %d,d1.c - %d,d1.d - %d,d1.e - %d,d1.f -
%d,d1.g - %d,d1.h - %d\n",d1.a,d1.b,d1.c,d1.d,d1.e,d1.f,d1.g,d1.h);
Thx in advans,
Karthik Balaguru

#include<stdio.h>
int main(void)
{
union dumdum {
unsigned char all_of_it;
struct {
unsigned int a : 1;
unsigned int b : 1;
unsigned int c : 1;
unsigned int d : 1;
unsigned int e : 1;
unsigned int f : 1;
unsigned int g : 1;
unsigned int h : 1;
} dummy;
};
union dumdum d1;
d1.dummy.a = 1;
d1.dummy.b = 1;
d1.dummy.c = 1;
d1.dummy.d = 1;
d1.dummy.e = 1;
d1.dummy.f = 1;
d1.dummy.g = 1;
d1.dummy.h = 1;
printf("d1.dummy.a is %x\n", (int)(d1.dummy.a == 1));
printf("d1.dummy.b is %x\n", (int)(d1.dummy.b == 1));
printf("d1.dummy.c is %x\n", (int)(d1.dummy.c == 1));
printf("d1.dummy.d is %x\n", (int)(d1.dummy.d == 1));
printf("d1.dummy.e is %x\n", (int)(d1.dummy.e == 1));
printf("d1.dummy.f is %x\n", (int)(d1.dummy.f == 1));
printf("d1.dummy.g is %x\n", (int)(d1.dummy.g == 1));
printf("d1.dummy.h is %x\n", (int)(d1.dummy.h == 1));
printf("which are all little slices of %x\n", (int)d1.all_of_it);
return 0;

}


Cool idea .

Karthik Balaguru
 
L

luser-ex-troll

It is best to snip sigs.

ack.


This char need not "overlap" any of the bit fields if sizeof(struct
dummy) > 1.

um...really? ok. [!?]
even on a machine with 8bit bytes?
I think is it better to use an array of unsigned char whose size is
sizeof(struct dummy).  You can to this by using memcpy and then you
can dispense with the union.

This is general advice: to investigate the representation of a C
object, treat it as an array of unsigned char.

Yes. Agreed.
The posted function was intended merely to illustrate
that you must feed printf an argument of the appropriate
width for the conversion specifier.

laser-extra-glow
 
C

CBFalconer

luser-ex-troll said:
.... snip ...


#include<stdio.h>
int main(void) {
union dumdum {
unsigned char all_of_it;
struct {
unsigned int a : 1;
unsigned int b : 1;
unsigned int c : 1;
unsigned int d : 1;
unsigned int e : 1;
unsigned int f : 1;
unsigned int g : 1;
unsigned int h : 1;
} dummy;
};
union dumdum d1;
d1.dummy.a = 1;
d1.dummy.b = 1;
d1.dummy.c = 1;
d1.dummy.d = 1;
d1.dummy.e = 1;
d1.dummy.f = 1;
d1.dummy.g = 1;
d1.dummy.h = 1;
printf("d1.dummy.a is %x\n", (int)(d1.dummy.a == 1));
printf("d1.dummy.b is %x\n", (int)(d1.dummy.b == 1));
printf("d1.dummy.c is %x\n", (int)(d1.dummy.c == 1));
printf("d1.dummy.d is %x\n", (int)(d1.dummy.d == 1));
printf("d1.dummy.e is %x\n", (int)(d1.dummy.e == 1));
printf("d1.dummy.f is %x\n", (int)(d1.dummy.f == 1));
printf("d1.dummy.g is %x\n", (int)(d1.dummy.g == 1));
printf("d1.dummy.h is %x\n", (int)(d1.dummy.h == 1));
printf("which are all little slices of %x\n", (int)d1.all_of_it);
return 0;
}

Doesn't work. You have no idea which bit(s) are assigned to which
item.
 
K

karthikbalaguru

It is best to snip sigs.


This char need not "overlap" any of the bit fields if sizeof(struct
dummy) > 1.


I think is it better to use an array of unsigned char whose size is
sizeof(struct dummy). You can to this by using memcpy and then you
can dispense with the union.

This is general advice: to investigate the representation of a C
object, treat it as an array of unsigned char.

Good tip. Thx .

Karthik Balaguru
 
J

jameskuyper

luser-ex-troll said:
This char need not "overlap" any of the bit fields if sizeof(struct
dummy) > 1.

um...really? ok. [!?]
Yes.

even on a machine with 8bit bytes?
Yes.

That struct could be two, four, or even 8 bytes long, usually because
of alignment issues. The standard does not specify which bytes those
bit fields are stored in, and it's entirely possible that they are
stored in some byte other than the first one of the struct - the last
byte of the struct is the most likely alternative.
 
B

Ben Bacarisse

karthikbalaguru said:
On Mar 18, 7:36 am, luser-ex-troll <[email protected]> wrote:

Cool idea .

Is it? It does not do anything useful as far as I can see.

If you know your struct is the same size as an int (it may not be) and
you know that int has no padding bits, then you can use a union with
an int member but the most flexible way to inspect the representation
of any C object is to treat it as an array of some char type (unsigned
char is usually best).
 
B

Ben Bacarisse

luser-ex-troll said:
luser-ex-troll <[email protected]> writes:

This char need not "overlap" any of the bit fields if sizeof(struct
dummy) > 1.

um...really? ok. [!?]
even on a machine with 8bit bytes?

Yes. I have used implementations where the smallest struct is two
bytes and you don't know which bits get used first when a bunch of
bit fields is declared. They may well be in a region that does not
overlap the char member.

Its fine (I think) if sizeof struct dummy == 1.

The posted function was intended merely to illustrate
that you must feed printf an argument of the appropriate
width for the conversion specifier.

This is not technically true or, at best, a little confusing since the
arguments that follow are promoted so the "width" is unlikely to be
what you think it is.
 
K

Keith Thompson

Ben Bacarisse said:
If you know your struct is the same size as an int (it may not be) and
you know that int has no padding bits, then you can use a union with
an int member but the most flexible way to inspect the representation
of any C object is to treat it as an array of some char type (unsigned
char is usually best).

Usually? When is unsigned char not best?
 
B

Ben Bacarisse

Keith Thompson said:
Usually? When is unsigned char not best?

Yes, it would have been better to be absolute about it.

You can't do better than unsigned char, but there are cases where it
is no better than char. This is the sort of code that is often not
portable and if you know that char will do, you might prefer the
shorter name, though that is about the weakest arguments imaginable.
 
B

Barry Schwarz

I think you really mean:

printf("d1.a-d1.h = %lx\n", (unsigned long)d1.a +
((unsigned long)d1.b<<4) +
((unsigned long)d1.c<<8) +
((unsigned long)d1.d<<12) +
((unsigned long)d1.e<<16) +
((unsigned long)d1.f<<20) +
((unsigned long)d1.g<<24) +
((unsigned long)d1.h<<28));

<< does have lower precendence than +

Quite so.
 

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,744
Messages
2,569,483
Members
44,903
Latest member
orderPeak8CBDGummies

Latest Threads

Top