Asked  7 Months ago    Answers:  5   Viewed   95 times

What does the following C++ code mean?

unsigned char a : 1; 
unsigned char b : 7;

I guess it creates two char a and b, and both of them should be one byte long, but I have no idea what the ": 1" and ": 7" part does.

 Answers

80

The 1 and the 7 are bit sizes to limit the range of the values. They're typically found in structures and unions. For example, on some systems (depends on char width and packing rules, etc), the code:

typedef struct {
    unsigned char a : 1;
    unsigned char b : 7;
} tOneAndSevenBits;

creates an 8-bit value, one bit for a and 7 bits for b.

Typically used in C to access "compressed" values such as a 4-bit nybble which might be contained in the top half of an 8-bit char:

typedef struct {
    unsigned char leftFour  : 4;
    unsigned char rightFour : 4;
} tTwoNybbles;

For the language lawyers amongst us, the 9.6 section of the C++11 standard explains this in detail, slightly paraphrased:


Bit-fields [class.bit]

A member-declarator of the form

     identifieropt   attribute-specifieropt   :   constant-expression

specifies a bit-field; its length is set off from the bit-field name by a colon. The optional attribute-specifier appertains to the entity being declared. The bit-field attribute is not part of the type of the class member.

The constant-expression shall be an integral constant expression with a value greater than or equal to zero. The value of the integral constant expression may be larger than the number of bits in the object representation of the bit-field’s type; in such cases the extra bits are used as padding bits and do not participate in the value representation of the bit-field.

Allocation of bit-fields within a class object is implementation-defined. Alignment of bit-fields is implementation-defined. Bit-fields are packed into some addressable allocation unit.

Note: bit-fields straddle allocation units on some machines and not on others. Bit-fields are assigned right-to-left on some machines, left-to-right on others. - end note

Tuesday, June 1, 2021
 
Daveel
answered 7 Months ago
13

Spaces indicate matching against descendants. For every space, you're descending (at least) one level and applying your selector to the children of the previously selected elements.

For example:

div.container.post

Will match a <div> with the container and post classes, while the following:

div.container .post

...will match any element with the class post which descend from a <div> with a class of container.

This will match <div class="container"><p class="post"></p></div>, but it will also match any .post, no matter how deeply nested it is:

<div class="container">
  <div>
    <div>
      <a class="post"> <!-- matched -->
    </div>
  </div>
</div>

You can think of it as matching in stages: First elements matching div.container are found, and then each of those elements (and all of their sub elements) are searched matches against .post.

In your case, div.Object :last first finds all <div> tags with the Object class, and then searches within each of those for elements matching :last, that is any element which is the last element in its container. This applies to both <div index="1">stuff</div> and <div>stuff</div>.

Spaces work exactly the same way as chaining multiple calls to find, so if you understand how that works, you can understand how spaces affect a selector. These are identical:

$('div#post ul.tags li');
$('div#post').find('ul.tags').find('li');
Sunday, July 18, 2021
 
Asher
answered 5 Months ago
10
void shiftl128 (
    unsigned int& a,
    unsigned int& b,
    unsigned int& c,
    unsigned int& d,
    size_t k)
{
    assert (k <= 128);
    if (k >= 32) // shifting a 32-bit integer by more than 31 bits is "undefined"
    {
        a=b;
        b=c;
        c=d;
        d=0;
        shiftl128(a,b,c,d,k-32);
    }
    else
    {
        a = (a << k) | (b >> (32-k));
        b = (b << k) | (c >> (32-k));
        c = (c << k) | (d >> (32-k));
        d = (d << k);
    }
}

void shiftr128 (
    unsigned int& a,
    unsigned int& b,
    unsigned int& c,
    unsigned int& d,
    size_t k)
{
    assert (k <= 128);
    if (k >= 32) // shifting a 32-bit integer by more than 31 bits is "undefined"
    {
        d=c;
        c=b;
        b=a;
        a=0;
        shiftr128(a,b,c,d,k-32);
    }
    else
    {
        d = (c << (32-k)) | (d >> k); 
        c = (b << (32-k)) | (c >> k); 
        b = (a << (32-k)) | (b >> k); 
        a = (a >> k);
    }
}
Friday, July 30, 2021
 
nirvair
answered 5 Months ago
92

It declares a bit field. The number specifies the size of that member in bits.

Saturday, August 7, 2021
 
PiyaModi
answered 4 Months ago
27

Because approach nr. 2 actually uses 100 bits of storage, plus some very minor (constant) overhead, while nr. 1 typically uses four bytes of storage per Bit structure. In general, a struct is at least one byte large per the C++ standard.

#include <bitset>
#include <iostream>

struct Bit { int data : 1; };

int main()
{
    Bit a[100];
    std::bitset<100> b;
    std::cout << sizeof(a) << "n";
    std::cout << sizeof(b) << "n";
}

prints

400
16

Apart from this, bitset wraps your bit array in a nice object representation with many useful operations.

Tuesday, September 14, 2021
 
adelbertc
answered 3 Months ago
Only authorized users can answer the question. Please sign in first, or register a free account.
Not the answer you're looking for? Browse other questions tagged :
 
Share