Type length in bits?

Discussion in 'C++' started by Angel Tsankov, Apr 24, 2011.

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


    --
    [ See http://www.gotw.ca/resources/clcm.htm for info about ]
    [ comp.lang.c++.moderated. First time posters: Do this! ]
    Angel Tsankov, Apr 24, 2011
    #1
    1. Advertising

  2. Angel Tsankov

    Paul Guest

    "Angel Tsankov" <> wrote in message
    news:...
    >
    > 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.
    Paul, Apr 24, 2011
    #2
    1. Advertising

  3. "Francis Glassborow" <> schrieb im
    Newsbeitrag news:...
    >
    > 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?

    --
    Matthias Hofmann
    Anvil-Soft, CEO
    http://www.anvil-soft.com - The Creators of Toilet Tycoon
    http://www.anvil-soft.de - Die Macher des Klomanagers



    [ See http://www.gotw.ca/resources/clcm.htm for info about ]
    [ comp.lang.c++.moderated. First time posters: Do this! ]
    Matthias Hofmann, Apr 29, 2011
    #3
  4. Angel Tsankov

    James Kanze Guest

    On Apr 30, 12:25 am, "Alf P. Steinbach /Usenet"
    <> wrote:
    > * Matthias Hofmann, on 29.04.2011 02:55:
    > > "Alf P. Steinbach /Usenet"<> schrieb im
    > > Newsbeitragnews:ip3phm$r9n$...

    >
    > >> C++98 §3.9.1/1:


    > >> "For character types, all bits of the object representation participate
    > >> in the value representation. For unsigned character types, all possible
    > >> bit patterns of the value representation represent numbers. These
    > >> requirements do not hold for other types."


    > >> And this language was unchanged in C++0x draft N3126, where it is the same
    > >> paragraph number.


    > > So if I understand this correctly, for types "char" and
    > > "signed char", there may be bit patterns that do not
    > > represent numbers, unless "char" is an unsigned type?


    > Right.


    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.

    --
    James Kanze


    [ See http://www.gotw.ca/resources/clcm.htm for info about ]
    [ comp.lang.c++.moderated. First time posters: Do this! ]
    James Kanze, May 1, 2011
    #4
  5. Angel Tsankov

    James Kanze Guest

    On Apr 30, 1:19 am, Francis Glassborow
    <> wrote:

    [...]
    > 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.

    --
    James Kanze


    [ See http://www.gotw.ca/resources/clcm.htm for info about ]
    [ comp.lang.c++.moderated. First time posters: Do this! ]
    James Kanze, May 1, 2011
    #5
  6. "James Kanze" <> schrieb im Newsbeitrag
    news:...
    > On Apr 30, 12:25 am, "Alf P. Steinbach /Usenet"
    > <> wrote:
    >> * Matthias Hofmann, on 29.04.2011 02:55:

    >
    >>> So if I understand this correctly, for types "char" and
    >>> "signed char", there may be bit patterns that do not
    >>> represent numbers, unless "char" is an unsigned type?

    >
    >> Right.

    >
    > 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

    --
    Matthias Hofmann
    Anvil-Soft, CEO
    http://www.anvil-soft.com - The Creators of Toilet Tycoon
    http://www.anvil-soft.de - Die Macher des Klomanagers



    [ See http://www.gotw.ca/resources/clcm.htm for info about ]
    [ comp.lang.c++.moderated. First time posters: Do this! ]
    Matthias Hofmann, May 2, 2011
    #6
  7. Angel Tsankov

    James Kanze Guest

    On May 2, 8:13 pm, "Matthias Hofmann" <> wrote:
    > "James Kanze" <> schrieb im
    > Newsbeitragnews:...


    > > On Apr 30, 12:25 am, "Alf P. Steinbach /Usenet"
    > > <> wrote:
    > >> * Matthias Hofmann, on 29.04.2011 02:55:


    > >>> So if I understand this correctly, for types "char" and
    > >>> "signed char", there may be bit patterns that do not
    > >>> represent numbers, unless "char" is an unsigned type?


    > >> Right.


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


    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.

    --
    James Kanze

    [ See http://www.gotw.ca/resources/clcm.htm for info about ]
    [ comp.lang.c++.moderated. First time posters: Do this! ]
    James Kanze, May 3, 2011
    #7
  8. "Bart van Ingen Schenau" <> schrieb im Newsbeitrag news:ipr9ha$92o$...
    >
    > Matthias Hofmann Wrote:
    >
    >> I there actually a difference between the << and the >> operator with
    >> respect to the number of positions that can be shifted?

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

    --
    Matthias Hofmann
    Anvil-Soft, CEO
    http://www.anvil-soft.com - The Creators of Toilet Tycoon
    http://www.anvil-soft.de - Die Macher des Klomanagers


    [ See http://www.gotw.ca/resources/clcm.htm for info about ]
    [ comp.lang.c++.moderated. First time posters: Do this! ]
    Matthias Hofmann, May 14, 2011
    #8
    1. Advertising

Want to reply to this thread or ask your own question?

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. GGG
    Replies:
    10
    Views:
    12,549
    Donar
    Jul 6, 2006
  2. sarmin kho
    Replies:
    2
    Views:
    825
    A. Lloyd Flanagan
    Jun 15, 2004
  3. Miki Tebeka
    Replies:
    1
    Views:
    443
    Marcin 'Qrczak' Kowalczyk
    Jun 14, 2004
  4. sergey

    "casting" bits to bits?

    sergey, Nov 8, 2006, in forum: VHDL
    Replies:
    1
    Views:
    704
    sergey
    Nov 8, 2006
  5. Tomás

    Value Bits Vs Object Bits

    Tomás, Jun 2, 2006, in forum: C Programming
    Replies:
    13
    Views:
    546
    Hallvard B Furuseth
    Jul 1, 2006
Loading...

Share This Page