to calculate bitsize of a byte

K

Keith Thompson

Richard G. Riley said:
I would hope so : I was more referring to the fact that a lot of
people wanted to muddy the waters with run time calculations of byte
size as opposed to compile time constants. "char" is easier because it
is a defined type so doing the bit shift really can and does work
without any worries of "purity" ...

If char is signed, a left shift that overflows invokes undefined
behavior. You can reliably shift an *unsigned* char to determine the
number of bits.

#include<stdio.h>
#include<limits.h>
int main(void)
{
int bits = 0;
unsigned char x = 1;
while (x != 0) {
x <<= 1;
bits ++;
}
printf("bits = %d\n", bits);
if (bits != CHAR_BIT) {
printf("CHAR_BIT = %d (OOPS!)\n", CHAR_BIT);
}
return 0;
}
 
M

Martin Ambuhl

The OP also said it was an _interview_ question. If it came from Microsoft,
you'd be expected to _calculate_ it, not look it up. If you fail a simple
example like this on a job interview, your chances of getting the job
decrease. That's reality, whether you think it's immature or not.

If you create a program to satisfy your childish idea of what
"calculate" means, the interviewer will know that you neither know C nor
do you have a clue about how to program. Successful programming
involves not doing extra work, spinning your wheels, just to avoid using
the obviously available.
 
E

Emmanuel Delahaye

david ullua a écrit :
I am reading "Joel on Software" these days, and am in stuck with the
question of "how to calculate bitsize of a byte" which is listed as one
of the basic interview questions in Joel's book. Anyone could give some
ideas?I am expecting your reply.

Quite simple.
1 - Include <limits.h>
2 - printout the value of CHAR_BIT.
Done.
 
E

Emmanuel Delahaye

david ullua a écrit :
Thanks for both of your reply.
I take a look at limits.h and other head files, there is really
something need to be read.

/Your/ C-book needs to be read from cover to cover. every 6 month.
 
P

pete

Keith Thompson wrote:
If char is signed, a left shift that overflows invokes undefined
behavior. You can reliably shift an *unsigned* char to determine the
number of bits.

Not if UCHAR_MAX equals INT_MAX, which it may.
 
J

Jordan Abel

Not if UCHAR_MAX equals INT_MAX, which it may.

Eh?

No, because you can keep left-shifting the unsigned char and the
behavior of an unsigned type on "overflow" is perfectly well-defined

what does int have to do with anything?
 
S

stathis gotsis

To complicate matters, char is not required by the C standard to be the
machine "byte". It is only required to be at least 8 bits. And a
machine "byte" is not always 8 bits. And some ancient beasts even
enables the programmer to specify how many bits are in a byte. So on
those machines (I believe Unisys was one) you "defined" how many bits
was in a byte rather than test it.


So you are saying that there are two bytes: the "machine byte" and the "C
implementation byte"? I assume that because the C standard clearly states
that char is equivalent to byte.
Your code fails on a machine with 6 bit bytes and a C compiler with 12
bit chars (remember 6 bit bytes are not allowed by the standard).

How can such as system exist then?
 
P

pete

Jordan said:
Eh?

No, because you can keep left-shifting the unsigned char and the
behavior of an unsigned type on "overflow" is perfectly well-defined

what does int have to do with anything?

Look up "integer promotions"

If INT_MAX is greater than or equal to UCHAR_MAX
then the shift operator will cause the unsigned char expression
to be promoted to type int.

If INT_MAX is equal to UCHAR_MAX,
then the final iteration is equivalent to
byte = INT_MAX << 1

unsigned short has the same problem.
You can't portably increment unsigned types until they roll over,
if they are lower ranking than int.
 
J

John F

david ullua said:
I am reading "Joel on Software" these days, and am in stuck with the
question of "how to calculate bitsize of a byte" which is listed as one
of the basic interview questions in Joel's book. Anyone could give some
ideas?I am expecting your reply.
David.

Try this:

unsigned char x = 0;
unsigned int y = INT_MAX; /*assuming less than MAX_INT bits*/

while( y )
{
x |= 1;
x <<= 1
}

while( x >>= 1 )
y++;

now y should give the number of bits in a char...

regards
John.
 
P

Peter Nilsson

stathis said:
So you are saying that there are two bytes: the "machine byte" and the "C
implementation byte"? I assume that because the C standard clearly states
that char is equivalent to byte.

Yes, which is why it's best to use the term 'byte' in the C language
sense,
and terms like octet or machine word for other senses.
How can such as system exist then?

The same way a C90 program can construct 64-bit pseudo ints from two
unsigned longs (which are only guaranteed to be at least 32-bits each.)
 
P

Peter Nilsson

Rod said:
... The question was how to _calculate_ the bits in a byte. Looking up
CHAR_BIT is not a calculation.

So it's not possible to enter 8 on a calculator, hit enter, and expect
to
see 8 as the result? My 20 year old pocket calculator must really be
out of date...
 
J

Jordan Abel

Look up "integer promotions"

If INT_MAX is greater than or equal to UCHAR_MAX then the shift
operator will cause the unsigned char expression to be promoted to
type int.

You're assuming that the right-hand operand is of type int.
If INT_MAX is equal to UCHAR_MAX,
then the final iteration is equivalent to
byte = INT_MAX << 1

unsigned short has the same problem.
You can't portably increment unsigned types until they roll over,
if they are lower ranking than int.

Why not?

unsigned short x = 1;

x <<= (unsigned short)1;
/* 15 more or however many times */

or even

x <<= 1U; [it'll promote to unsigned int and safely drop back down]
 
P

Peter Nilsson

pete said:
If INT_MAX is equal to UCHAR_MAX,
then the final iteration is equivalent to
byte = INT_MAX << 1

unsigned short has the same problem.
You can't portably increment unsigned types until they roll over,
if they are lower ranking than int.

But you can do...

my_unsigned_short += 1u;

What Keith needed was...

x *= 2u;
 
P

Peter Nilsson

Jordan said:
You're assuming that the right-hand operand is of type int.

No. The integral promotion is only relevant to the left hand operand of
shift
expressions.
Why not?

unsigned short x = 1;

x <<= (unsigned short)1;
/* 15 more or however many times */

Because if USHRT_MAX <= INT_MAX, then you'll eventually be doing...

x = (INT_MAX/2+1) << 1
or even

x <<= 1U; [it'll promote to unsigned int and safely drop back down]

No, the two operands of shift operators are not subject to arithmetic
promotion.
 
J

Jordan Abel

No. The integral promotion is only relevant to the left hand operand
of shift expressions.

Then what could cause the left-hand operand (being, as established,
unsigned char) to be promoted to int at all? Is there some magical "all
types narrower than int get promed to int all the time no matter what"
rule i haven't heard about?

It's not clear how

x {is unsigned short} <<= 1U

causes anything to be promoted to any signed type.
Because if USHRT_MAX <= INT_MAX, then you'll eventually be doing...

x = (INT_MAX/2+1) << 1

I assume you mean

x = (unsigned short)(INT_MAX/2+1) << (unsigned short)1
or even

x <<= 1U; [it'll promote to unsigned int and safely drop back down]

No, the two operands of shift operators are not subject to arithmetic
promotion.

But your entire POINT rides on having it be promoted to signed int if
you use 1 instead of 1U or (unsigned short)1!
 
M

Micah Cowan

Walter Bright said:
There's a bug. If char is signed, the c>0 will stop one bit short. Try c!=0.
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
If he's (un)lucky...

-Micah
 
S

stathis gotsis

Peter Nilsson said:
Yes, which is why it's best to use the term 'byte' in the C language
sense,
and terms like octet or machine word for other senses.

Thank you for your answer.
The same way a C90 program can construct 64-bit pseudo ints from two
unsigned longs (which are only guaranteed to be at least 32-bits each.)

I misread the previous poster's comment. Yes, such a system can exist. I
thought the OP referred to the implementation's byte size, as oppposed to
the machine's. One cannot determine the machine's byte size through C
because a C implementation may hide the HW details.
 
K

Keith Thompson

Martin Ambuhl said:
If you create a program to satisfy your childish idea of what
"calculate" means, the interviewer will know that you neither know C
nor do you have a clue about how to program. Successful programming
involves not doing extra work, spinning your wheels, just to avoid
using the obviously available.

If an interviewer asked me how to calculate the number of bits in a
byte in C, I'd say "look at CHAR_BIT in <limits.h>". If he says, "Ok,
how would you do it without using CHAR_BIT", *then* I'd think about
how to do it by shifting bits. If I'm penalized for giving a correct
answer, it's likely not someplace I want to work.

Conceivably someone might try to guess what the interviewer means and
try to give the answer he wants, avoiding the simple and correct
answer, but that approach is likely to backfire; it's just as likely
the interviewer wanted to see whether I know about CHAR_BIT. In any
case, interview strategies beyond giving correct answers are beyond
the scope of this newsgroup.
 
P

Peter Nilsson

Jordan said:
Then what could cause the left-hand operand (being, as established,
unsigned char) to be promoted to int at all? Is there some magical "all
types narrower than int get promed to int all the time no matter what"
rule i haven't heard about?

Not "no matter what", but generally they do get promoted as per
6.3.1.1p2.
The fact of 6.3.1.1p3 makes the integer promotion of the right hand
operand (of a shift operator) incidental.
It's not clear how

x {is unsigned short} <<= 1U

causes anything to be promoted to any signed type.

In cases where USHRT_MAX <= INT_MAX, we have...

x <<= 1u;
x = x << 1u;
x = ((int) x) << 1u;

....all being identical. The u suffix in 1u is irrelevant here, it's the
integral
promotion of x from unsigned short to int that may occur.

If, for the same premice, we instead have...

x += 1u;
x = x + 1u;

Then arithmetic conversion occurs on top of the integral promotion...

x = (unsigned) (int) x + 1u;

Whilst arithmetic conversion applies to binary +, it does not apply to
<<.

I assume you mean

x = (unsigned short)(INT_MAX/2+1) << (unsigned short)1

Given the initial premice, they have the same semantics. Even the
explicit cast to (unsigned short) will not prevent integral promotion
from applying to the left operand.
or even

x <<= 1U; [it'll promote to unsigned int and safely drop back down]

No, the two operands of shift operators are not subject to arithmetic
promotion.

But your entire POINT rides on having it be promoted to signed int if
you use 1 instead of 1U or (unsigned short)1!

No. I think you haven't yet seen the difference between integral
promotion
and arithmetic conversion.
 
J

Jordan Abel

Not "no matter what", but generally they do get promoted as per
6.3.1.1p2.
The fact of 6.3.1.1p3 makes the integer promotion of the right hand
operand (of a shift operator) incidental.


In cases where USHRT_MAX <= INT_MAX, we have...

x <<= 1u;
x = x << 1u;
x = ((int) x) << 1u;

...all being identical. The u suffix in 1u is irrelevant here, it's the
integral
promotion of x from unsigned short to int that may occur.

Why is anything being promoted to a type that is not the type of any
subexpression that is involved in the expression?
If, for the same premice, we instead have...

x += 1u;
x = x + 1u;

Then arithmetic conversion occurs on top of the integral promotion...

x = (unsigned) (int) x + 1u;

Whilst arithmetic conversion applies to binary +, it does not apply to
<<.



Given the initial premice, they have the same semantics. Even the
explicit cast to (unsigned short) will not prevent integral promotion
from applying to the left operand.

But where is this "integral promotion" coming from. I thought that a
value in an expression could only be promoted to the type of another
value involved in the same expression - not some random type (int) found
elsewhere.
or even

x <<= 1U; [it'll promote to unsigned int and safely drop back down]

No, the two operands of shift operators are not subject to arithmetic
promotion.

But your entire POINT rides on having it be promoted to signed int if
you use 1 instead of 1U or (unsigned short)1!

No. I think you haven't yet seen the difference between integral
promotion and arithmetic conversion.

Eh - It seems illogical, so I checked the standard [actually an
anonymous c89 draft, but close enough to the standard, doubt it's been
changed]

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 integral promotions.

Incidentally, UCHAR_MAX cannot be the same as INT_MAX, because int has a
sign bit, and unsigned char may not have padding bits.
 

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
474,176
Messages
2,570,950
Members
47,500
Latest member
ArianneJsb

Latest Threads

Top