Portable/standard way of counting number of bits in variable?

  • Follow


Is there a portable/standard way of counting the
number of bits in a variable.  The following for
statement works on all the machines I've tried:

#include <stdio.h>
int main(void) {
 int n;
 unsigned long int a;

 for (n = 0, a = 1;  a != 0;  a <<= 1, n++) ;

 printf("unsigned long int has %d bits.\n", n);
 return 0;
}

Produces:
unsigned long int has 32 bits.

I don't want to depend on C standard built-in defines.
I want to check this during program execution.

-- 
Dale Dellutri <ddelQQQlutr@panQQQix.com> (lose the Q's)
0
Reply ddelQQQlutr (156) 4/2/2009 3:31:41 PM

On Thu, 2 Apr 2009 15:31:41 +0000 (UTC), Dale Dellutri
<ddelQQQlutr@panQQQix.com> wrote:

>Is there a portable/standard way of counting the
>number of bits in a variable.

With CHAR_BIT from limits.h and the sizeof operator.

[snip...snip...]
>I don't want to depend on C standard built-in defines.
>I want to check this during program execution.

If you don't trust the compiler to get sizeof right, why believe that it
will do anything else correctly?

-- 
Rich Webb     Norfolk, VA
0
Reply bbew.ar (758) 4/2/2009 3:50:26 PM


On Thu, 02 Apr 2009 11:50:26 -0400, Rich Webb <bbew.ar@mapson.nozirev.ten> wrote:
> On Thu, 2 Apr 2009 15:31:41 +0000 (UTC), Dale Dellutri
> <ddelQQQlutr@panQQQix.com> wrote:

> >Is there a portable/standard way of counting the
> >number of bits in a variable.

> With CHAR_BIT from limits.h and the sizeof operator.

> [snip...snip...]
> >I don't want to depend on C standard built-in defines.
> >I want to check this during program execution.

> If you don't trust the compiler to get sizeof right, why believe that it
> will do anything else correctly?

Probably because I knew about sizeof but not CHAR_BIT.

Thanks.

-- 
Dale Dellutri <ddelQQQlutr@panQQQix.com> (lose the Q's)
0
Reply ddelQQQlutr (156) 4/2/2009 4:15:05 PM

Dale Dellutri wrote:
> Is there a portable/standard way of counting the
> number of bits in a variable.  The following for
> statement works on all the machines I've tried:
> 
> #include <stdio.h>
> int main(void) {
>  int n;
>  unsigned long int a;
> 
>  for (n = 0, a = 1;  a != 0;  a <<= 1, n++) ;
> 
>  printf("unsigned long int has %d bits.\n", n);
>  return 0;
> }
> 
> Produces:
> unsigned long int has 32 bits.

     The method you've shown works for all unsigned integer
types, even for unsigned bit-fields.  `CHAR_BIT * sizeof a'
is likely to work but ignores the nagging possibility of
padding bits (and, of course, won't work with bit-fields).

     For signed types (including, possibly, `char'), you
must not attempt to shift a 1-bit into the sign position.
So I'd suggest initializing the variable to xxx_MAX and
right-shifting until you reach zero to count the value
bits, adding one if you also want to count the sign.  I
can't think of a way to make this work for bit-fields,
since there's no xxx_MAX macro to appeal to.  (It's
tempting to start at -1 and right-shift until you reach
zero, but right-shifting a negative integer is not well
defined -- on some machines you'd conclude that a signed
integer has an infinite number of bits!)

     I can't think of a way to do this for floating-point
types.  `CHAR_BIT * sizeof a' gives an upper bound, and
you could compute a lower bound from some <float.h> values,
and if they happened to agree you'd know.  But if the
upper and lower bounds turned out different, I don't know
how you could refine them.

     Pointer types look like a lost cause.  Upper bound
via sizeof, but ...  There's also a definitional problem:
In a pointer to a type that might have non-trivial alignment
requirements -- e.g., an `int*' with four-byte alignment --
are the low-order "must be zero" bits considered part of
the "value," or not?

> I don't want to depend on C standard built-in defines.

     Why not?  What problem are you trying to solve?  Note
that even the unsigned-only solution requires you to know
how to write the name of the type, which implies that you
also know how to write the corresponding xxx_MAX macro.
`(int)(log(xxx_MAX + 1.0) / log(2.0) + 0.5)' should suffice.

> I want to check this during program execution.

     You're in luck, because I can't think of a way to get
the bit count at compile time.

-- 
Eric.Sosman@sun.com

0
Reply Eric.Sosman (4228) 4/2/2009 4:33:46 PM

On 2009-04-02, Dale Dellutri <ddelQQQlutr@panQQQix.com> wrote:
           ^^ 
You are a day late.

> unsigned long int has 32 bits.
>
> I don't want to depend on C standard built-in defines.
> I want to check this during program execution.

Why, do you suspect that this value can change at run-time?

For what other purpose would you defer to run time that which you can compute
at compile time?
0
Reply kkylheku (2499) 4/2/2009 4:43:53 PM

Dale Dellutri wrote:
> #include <stdio.h>
> int main(void) {
> int n;
> unsigned long int a;
>
> for (n = 0, a = 1;  a != 0;  a <<= 1, n++) ;
>
> printf("unsigned long int has %d bits.\n", n);
> return 0;
> }
>
> Produces:
> unsigned long int has 32 bits.

That doesn't take into account possible padding bits.

Moreover, if you do something similar for a signed integer type,
you invoke undefined behavior because of the integer overflow. 

Moreover, you must take into account integer promotions for types
with low rank.

Just stick with CHAR_BIT and sizeof.

> I don't want to depend on C standard built-in defines.
> I want to check this during program execution.

Why?


Yours,
Han from China

-- 
"Only entropy comes easy." -- Anton Chekhov

0
Reply autistic-pedantry (1030) 4/2/2009 4:46:51 PM

Han from China <autistic-pedantry@comp.lang.c> writes:

> Dale Dellutri wrote:
>> #include <stdio.h>
>> int main(void) {
>> int n;
>> unsigned long int a;
>>
>> for (n = 0, a = 1;  a != 0;  a <<= 1, n++) ;
>>
>> printf("unsigned long int has %d bits.\n", n);
>> return 0;
>> }
>>
>> Produces:
>> unsigned long int has 32 bits.
>
> That doesn't take into account possible padding bits.

Why would you care? Number of bits in a variable kind of means how many
bit can be used.

>
> Moreover, if you do something similar for a signed integer type,
> you invoke undefined behavior because of the integer overflow. 
>
> Moreover, you must take into account integer promotions for types
> with low rank.
>
> Just stick with CHAR_BIT and sizeof.
>
>> I don't want to depend on C standard built-in defines.
>> I want to check this during program execution.
>
> Why?
>
>
> Yours,
> Han from China

-- 
"Avoid hyperbole at all costs, its the most destructive argument on
the planet" - Mark McIntyre in comp.lang.c
0
Reply rgrdev_ (1087) 4/2/2009 5:06:35 PM

Dale Dellutri wrote:
> Is there a portable/standard way of counting the
> number of bits in a variable.  

There's number of bits in the 'object representation' and there's number 
of bits in the 'value representation'. You need to decide first, which 
one you need.

-- 
Best regards,
Andrey Tarasevich
0
Reply andreytarasevich (1531) 4/2/2009 6:27:01 PM

On Apr 2, 9:27=A0pm, Andrey Tarasevich <andreytarasev...@hotmail.com>
wrote:
> Dale Dellutri wrote:
> > Is there a portable/standard way of counting the
> > number of bits in a variable. =A0
>
> There's number of bits in the 'object representation' and there's number
> of bits in the 'value representation'. You need to decide first, which
> one you need.

There's no such thing as a value representation. The object
representation of an integer has value bits, optional padding bits and
a sign bit, if the integer is signed. Special case are expressions
with unsigned char type, which can not have any padding bits.

Operations on values ignore the representation and thus padding bits
are not taken into account.

0
Reply vippstar (1211) 4/3/2009 4:54:17 AM

Eric Sosman wrote:
> Dale Dellutri wrote:
> > Is there a portable/standard way of counting the
> > number of bits in a variable.
[...]
> > I want to check this during program execution.
> 
>      You're in luck, because I can't think of a way to get
> the bit count at compile time.

Someone posted a nifty macro a few months ago that determines how many
bits are needed to represent a given positive value that is a power of 2
minus one:

http://groups.google.com/group/comp.lang.c/browse_frm/thread/c48de16908e3ec82

> Hallvard B Furuseth once posted the following (which 
> I've edited slightly due to line wrap issues)... 
>
>� /* Number of bits in inttype_MAX, or in any (1<<b)-1 
>� where 0 <= b < 3E+10 */ 
>� #define IMAX_BITS(m) ((m) /((m)%0x3fffffffL+1) \ 
>� � /0x3fffffffL %0x3fffffffL *30 + \ 
>� � (m)%0x3fffffffL /((m)%31+1)/31%31*5 + 4 - \ 
>� � 12/((m)%31+3)) 

Seems to do the trick at compile-time. I don't think there's anything
gained by deferring it until run-time.
0
Reply blargg.ei3 (369) 4/3/2009 8:23:51 AM

vippstar@gmail.com wrote:
> On Apr 2, 9:27 pm, Andrey Tarasevich <andreytarasev...@hotmail.com>
> wrote:
>> Dale Dellutri wrote:
>>> Is there a portable/standard way of counting the
>>> number of bits in a variable.  
>> There's number of bits in the 'object representation' and there's number
>> of bits in the 'value representation'. You need to decide first, which
>> one you need.
> 
> There's no such thing as a value representation.  ...

The standard disagrees: "If there are N value bits, each bit shall 
represent a different power of 2 between 1 and 2N-1, so that objects of 
that type shall be capable of representing values from 0 to 2N -1 using 
a pure binary representation; this shall be known as the value 
representation." (6.2.6.2p1).

Oddly enough, since 6.2.6.2p1 only describes unsigned integers, the 
standard doesn't clarify whether sign bits should be considered to be 
part of the value representation - I think they should. Since the 
standard never uses the term again, this isn't any big problem. That's 
probably why the term is not marked as a definition by putting it in 
italics.

....
> Operations on values ignore the representation and thus padding bits
> are not taken into account.

The bit-wise operators (~, |, &, ^, <<, and >>) are all described as 
operating on bits. Since those operations don't deal with padding bits, 
that means that the bits they refer to make up the value representation 
(at least for unsigned types - the terminology is unclear for signed types).
0
Reply jameskuyper (5161) 4/3/2009 10:32:55 AM

On Apr 3, 1:32=A0pm, James Kuyper <jameskuy...@verizon.net> wrote:
> vipps...@gmail.com wrote:
> > On Apr 2, 9:27 pm, Andrey Tarasevich <andreytarasev...@hotmail.com>
> > wrote:
> >> There's number of bits in the 'object representation' and there's numb=
er
> >> of bits in the 'value representation'.
>
> > There's no such thing as a value representation.
>
> The standard disagrees: "If there are N value bits, each bit shall
> represent a different power of 2 between 1 and 2N-1, so that objects of
> that type shall be capable of representing values from 0 to 2N -1 using
> a pure binary representation; this shall be known as the value
> representation." (6.2.6.2p1).
>
> Oddly enough, since 6.2.6.2p1 only describes unsigned integers, the
> standard doesn't clarify whether sign bits should be considered to be
> part of the value representation - I think they should. Since the
> standard never uses the term again, this isn't any big problem. That's
> probably why the term is not marked as a definition by putting it in
> italics.

Ah, thanks. I haven't read that before, (value representation). I
disagree though that 6.2.6.1p1 applies for signed integers or that the
value representation includes the sign bit, because other rules
described in 6.2.6.1p1 also do not apply for signed integers, for
example, "each bit shall represent a different power of 2 between 1
and 2N-1", while ones' complement -1 does not satisfy this condition.

Therefore, either signed integers do not have a value representation,
or the standard has a defect (incomplete). IMHO it is the latter.

> > Operations on values ignore the representation and thus padding bits
> > are not taken into account.
>
> The bit-wise operators (~, |, &, ^, <<, and >>) are all described as
> operating on bits. Since those operations don't deal with padding bits,
> that means that the bits they refer to make up the value representation
> (at least for unsigned types - the terminology is unclear for signed type=
s).

I'm not sure if the terminology is unclear, but to my experience,
surely smaller than yours, bit-wise operations on signed integers
indicated a bug in the code, and I've never encountered a problem
which required such operations on signed integers.
0
Reply vippstar (1211) 4/3/2009 11:38:43 AM

vippstar@gmail.com wrote:
> On Apr 3, 1:32 pm, James Kuyper <jameskuy...@verizon.net> wrote:
....
>> Oddly enough, since 6.2.6.2p1 only describes unsigned integers, the
>> standard doesn't clarify whether sign bits should be considered to be
>> part of the value representation - I think they should. Since the
>> standard never uses the term again, this isn't any big problem. That's
>> probably why the term is not marked as a definition by putting it in
>> italics.
> 
> Ah, thanks. I haven't read that before, (value representation). I
> disagree though that 6.2.6.1p1 applies for signed integers or that the
> value representation includes the sign bit, because other rules
> described in 6.2.6.1p1 also do not apply for signed integers, for
> example, "each bit shall represent a different power of 2 between 1
> and 2N-1", while ones' complement -1 does not satisfy this condition.

I think the sign bit should be part of the value representation, because 
it plays a part in determining the value that is being represented.

> Therefore, either signed integers do not have a value representation,
> or the standard has a defect (incomplete). IMHO it is the latter.

I would consider the failure to specify a definition that applies to 
signed integers a defect, were it not for the fact that the standard 
never makes any use of the term, other than to define it.

>> The bit-wise operators (~, |, &, ^, <<, and >>) are all described as
>> operating on bits. Since those operations don't deal with padding bits,
>> that means that the bits they refer to make up the value representation
>> (at least for unsigned types - the terminology is unclear for signed types).
> 
> I'm not sure if the terminology is unclear, but to my experience,
> surely smaller than yours, bit-wise operations on signed integers
> indicated a bug in the code, and I've never encountered a problem
> which required such operations on signed integers.

I would certainly agree that bit-wise operations should only be perform 
on unsigned types. However, except for the shift operators, it is not 
undefined behavior to apply them to signed integers, not even if the 
signed integer has a negative value. The results are non-portable; but 
not necessarily a bug.
0
Reply jameskuyper (5161) 4/3/2009 12:36:43 PM

James Kuyper wrote:

> I would certainly agree that bit-wise operations should only be perform 
> on unsigned types. However, except for the shift operators, it is not 
> undefined behavior to apply them to signed integers, not even if the 
> signed integer has a negative value. The results are non-portable; but 
> not necessarily a bug.

The bitwise operators are capable of generating trap representations
when applied to int type expressions.

-- 
pete
0
Reply pfiland (6613) 4/3/2009 2:26:11 PM

Dale Dellutri wrote:
> Is there a portable/standard way of counting the
> number of bits in a variable.  The following for
> statement works on all the machines I've tried:
> 
> #include <stdio.h>
> int main(void) {
>  int n;
>  unsigned long int a;
> 
>  for (n = 0, a = 1;  a != 0;  a <<= 1, n++) ;
> 
>  printf("unsigned long int has %d bits.\n", n);
>  return 0;
> }
> 
> Produces:
> unsigned long int has 32 bits.
> 
> I don't want to depend on C standard built-in defines.
> I want to check this during program execution.
> 
I understand that this is an assignment in colleges/universities, since 
I had to do this one too.
You are doing just fine, you should not have portability problem with 
this solution.
0
Reply dfighter2 (43) 4/4/2009 3:40:16 PM

14 Replies
26 Views

(page loaded in 0.24 seconds)

Similiar Articles:


















7/12/2012 4:28:34 PM


Reply: