Type length in bits?

A

Angel Tsankov

What is a standard way to get the "length in bits" (in the sense of
5.8/1) of a type?
 
P

Paul

Angel Tsankov said:
What is a standard way to get the "length in bits" (in the sense of
5.8/1) of a type?
Hi,
I'm not sure if there is a standard way , but it depends on the length of
the orignal type.
If you have a long long and you left shift it, you won't get type promotion.
But you may have overflow or carry.
Here is one way to do it assuming the result fits into a promoted type.

int bits_per_byte = 8;
unsigned char uc = -1;
unsigned char shift_val = 1;

int num_bits = sizeof(uc)*bits_per_byte;
std::cout<< num_bits <<std::endl;
num_bits = sizeof(uc<< shift_val)*bits_per_byte;
std::cout<< num_bits;

If you change unsigned char uc , to an unsigned long type then this may not
work. I don't know if there is a way to get the number of bytes in that
case.
There is a way to get the value using floating point types , so therefore I
presume there is a way to do it. It an interested point worthy of more
thought IMO.

Note: There have been other suggestions to obtain a value for bits_per_byte
which may be more suitable in production code. I'm not sure if your question
was asking this simple point or the more complex point my answer has
addressed.
 
M

Matthias Hofmann

Francis Glassborow said:
I think there is a misunderstanding here. Fundamental types must use all
the bits in their value representation but that is not the same as the
amount of storage required. I.e. it is perfectly possible to have
64-bits of storage (8 octets) for an int but only use 32 bits for the
value representation.

If a type would not use certain bits in its value representation, than these
bits wouldn't be part of the value representation, would they?
 
J

James Kanze

* Matthias Hofmann, on 29.04.2011 02:55:

Not for plain char. In C++. (This is, I think, a difference
between C and C++. C allows trapping bit patterns in plain
char. Not that it makes a difference in practice.)

[...]
The standard mentions two's complement, one's complement and signed and
magnitude as possible representations.

The C standard mentions these three formats, and says that the
value representation must be one of them. The current (03) C++
standard is a lot vaguer.
Essentially the shift operators impose additional requirements
that rule out more esoteric representations (like gray code
:) ).

Both the C and the C++ standard explicitly require a pure binary
representation, which rules out greay code.
I don't think that was intentional; rather, that the goal was just
to allow the binary representations in use in the 1970's.
IMHO opinion it would have been nice if we could just ditch
the "ENIAC-support":

The problem is that it isn't just an issue for ENIAC. At least
one modern machine still uses signed magnitude, for example.
like, require two's complement, require well-defined operator
expressions, so on. But this has been discussed repeatedly and
at length before. I think C++0x was the point of final freeze
of adult features in C++, so to speak: since the change didn't
happen with C++0x it will never happen, so we're stuck with
the annoying behaviors along with the nicer ones... :-(

There should be at least some changes in C++0x, because there
was a serious incompatibility between C and C++, and it meant
that C++ couldn't be implemented on one modern machine, where as
C could.
 
J

James Kanze

On Apr 30, 1:19 am, Francis Glassborow

[...]
The problem for the OP is that whilst we can easily evaluate
the number of bits in a type's object representation I know of
no way to evaluate (you can look it up in the documentation)
the number of bits in the value representation.

It should be possible exploiting xxx_MAX in some way. In C++11,
std::numeric_limits<T>::max() should also be usable.
 
M

Matthias Hofmann

James Kanze said:
Not for plain char. In C++. (This is, I think, a difference
between C and C++. C allows trapping bit patterns in plain
char. Not that it makes a difference in practice.)

Yes, it does make a difference. Assuming that the standard allows a
conversion from a pointer to any object type to void* and back to char*, the
following two utility functions are legal:

// Converts a pointer of any non-const
// type to a non-const char pointer.
inline char* char_ptr( void* p ) throw()
{ return static_cast<char*>( p ); }

// Converts a pointer of any constant
// type to a constant char pointer.
inline const char* char_ptr( const void* p ) throw()
{ return static_cast<const char*>( p ); }

But what if the value of one byte accessed through such a char pointer is a
trap representation? Then iterating through the bytes of the underlying
object may cause the program to crash!

The answer seems to be using a pointer to unsigned char instead of plain
char, but there is a problem with that, too: 3.9.2/4 guarantees a char* to
have the same representation as a void*, but it does not give such a
guarantee to unsigned char*.

So how do you implement these two utility functions above? If you you a
plain char*, then you may have problems with bit patterns or sign expansion
errors, and if you use an unsigned char, then you have object representation
problems.

But if C++ does in fact not allow trapping bit patterns, then the problem is
solved and plain char should be used! So could you please refer me to the
corresponding section of the standard where I can find such a guarantee?

I can recommend the following links to earlier discussions on this newsgroup
for anyone who wants to delve deeper into this controversy:

About casting from T* to void* and from void* to char*:
http://groups.google.com/group/comp.lang.c++.moderated/msg/be54dcaab13a12c6

About the guarantee of being able to perform a static_cast from a pointer to
void to a pointer to any character type:
http://groups.google.com/group/comp.lang.c++.moderated/msg/81b1187f784d7274
 
J

James Kanze

Newsbeitragnews:ac3bc85f-aa5d-465b-b0c5-83ab1fac78fa@x18g2000yqe.googlegroups.com...
Yes, it does make a difference.

Not in practice, since no known implementation has ever had
trapping bit patterns in plain char. All known implementations
that don't use a straightforward 2's complement representation
make plain char unsigned.
Assuming that the standard allows a conversion from a pointer
to any object type to void* and back to char*, the following
two utility functions are legal:
// Converts a pointer of any non-const
// type to a non-const char pointer.
inline char* char_ptr( void* p ) throw()
{ return static_cast<char*>( p ); }
// Converts a pointer of any constant
// type to a constant char pointer.
inline const char* char_ptr( const void* p ) throw()
{ return static_cast<const char*>( p ); }
But what if the value of one byte accessed through such a char
pointer is a trap representation? Then iterating through the
bytes of the underlying object may cause the program to crash!

You can imagine implementations where such things might not
work. In practice, they don't exist.
The answer seems to be using a pointer to unsigned char
instead of plain char, but there is a problem with that, too:
3.9.2/4 guarantees a char* to have the same representation as
a void*, but it does not give such a guarantee to unsigned
char*.

That's probably an oversight. In general, the pointer
representations for the corresponding signed and unsigned types
should be the same. (In practice, they will be the same.)
So how do you implement these two utility functions above?

In practice, they're fine as they stand (although I prefer
unsigned char).
If you you a plain char*, then you may have problems with bit
patterns or sign expansion errors, and if you use an unsigned
char, then you have object representation problems.

In which real implementations?
But if C++ does in fact not allow trapping bit patterns, then
the problem is solved and plain char should be used! So could
you please refer me to the corresponding section of the
standard where I can find such a guarantee?

Not the standard, but compiler implementers want their compiler
to be used. If unsigned char* has a different representation
than char* (and I can't even imagine an architecture where this
wouldn't be the case), or if plain char actually does have
trapping representations (easily avoided by making plain char
unsigned), then the compiler won't be used.
 
M

Matthias Hofmann

Bart van Ingen Schenau said:
No, but the >> operator is not defined if the left-hand operand has a
value
< 0.

Really? So this is undefined behaviour? I thought that this would shift in
sign bits from the left, at least that's what happens on Microsoft Visual
C++ 6.0.
 

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,769
Messages
2,569,580
Members
45,055
Latest member
SlimSparkKetoACVReview

Latest Threads

Top