What Does C++ Struct Syntax "A: B" Mean

What does C++ struct syntax a : b mean

Bitfields, carried over from C. Name is 40 bits wide, Colour is 24 bits wide. Your struct therefore has at least 64 bits. On my system 64 bits would be 8 bytes.

: (colon) in C struct - what does it mean?

Those are bit fields. Basically, the number after the colon describes how many bits that field uses. Here is a quote from MSDN describing bit fields:

The constant-expression specifies the width of the field in bits. The
type-specifier for the declarator must be unsigned int, signed int, or
int, and the constant-expression must be a nonnegative integer value.
If the value is zero, the declaration has no declarator. Arrays of bit
fields, pointers to bit fields, and functions returning bit fields are
not allowed. The optional declarator names the bit field. Bit fields
can only be declared as part of a structure. The address-of operator
(&) cannot be applied to bit-field components.

Unnamed bit fields cannot be referenced, and their contents at run
time are unpredictable. They can be used as "dummy" fields, for
alignment purposes. An unnamed bit field whose width is specified as 0
guarantees that storage for the member following it in the
struct-declaration-list begins on an int boundary.

This example defines a two-dimensional array of structures named screen.

struct 
{
unsigned short icon : 8;
unsigned short color : 4;
unsigned short underline : 1;
unsigned short blink : 1;
} screen[25][80];

Edit: another important bit from the MSDN link:

Bit fields have the same semantics as the integer type. This means a
bit field is used in expressions in exactly the same way as a variable
of the same base type would be used, regardless of how many bits are
in the bit field.

A quick sample illustrates this nicely. Interestingly, with mixed types the compiler seems to default to sizeof (int).

  struct
{
int a : 4;
int b : 13;
int c : 1;
} test1;

struct
{
short a : 4;
short b : 3;
} test2;

struct
{
char a : 4;
char b : 3;
} test3;

struct
{
char a : 4;
short b : 3;
} test4;

printf("test1: %d\ntest2: %d\ntest3: %d\ntest4: %d\n", sizeof(test1), sizeof(test2), sizeof(test3), sizeof(test4));

test1: 4

test2: 2

test3: 1

test4: 4

typedef struct vs struct definitions

The common idiom is using both:

typedef struct S { 
int x;
} S;

They are different definitions. To make the discussion clearer I will split the sentence:

struct S { 
int x;
};

typedef struct S S;

In the first line you are defining the identifier S within the struct name space (not in the C++ sense). You can use it and define variables or function arguments of the newly defined type by defining the type of the argument as struct S:

void f( struct S argument ); // struct is required here

The second line adds a type alias S in the global name space and thus allows you to just write:

void f( S argument ); // struct keyword no longer needed

Note that since both identifier name spaces are different, defining S both in the structs and global spaces is not an error, as it is not redefining the same identifier, but rather creating a different identifier in a different place.

To make the difference clearer:

typedef struct S { 
int x;
} T;

void S() { } // correct

//void T() {} // error: symbol T already defined as an alias to 'struct S'

You can define a function with the same name of the struct as the identifiers are kept in different spaces, but you cannot define a function with the same name as a typedef as those identifiers collide.

In C++, it is slightly different as the rules to locate a symbol have changed subtly. C++ still keeps the two different identifier spaces, but unlike in C, when you only define the symbol within the class identifier space, you are not required to provide the struct/class keyword:

 // C++
struct S {
int x;
}; // S defined as a class

void f( S a ); // correct: struct is optional

What changes are the search rules, not where the identifiers are defined. The compiler will search the global identifier table and after S has not been found it will search for S within the class identifiers.

The code presented before behaves in the same way:

typedef struct S { 
int x;
} T;

void S() {} // correct [*]

//void T() {} // error: symbol T already defined as an alias to 'struct S'

After the definition of the S function in the second line, the struct S cannot be resolved automatically by the compiler, and to create an object or define an argument of that type you must fall back to including the struct keyword:

// previous code here...
int main() {
S();
struct S s;
}

C structure syntax

C typedef declarations are understood by analogy with variable declarations.

int a, *b;

declares the values a of type int and b of type int*.

typedef int A, *B;

declares the type A equivalent to int and the type B equivalent to int*. So, just think about what the variable type would be if this was a variable declaration.

So yes, PUKWD_USB_DEVICE_INFO becomes equivalent to struct _UKWD_USB_DEVICE_INFO*.

EDIT

Also, the space does not matter. C is a whitespace language. The extra aliases are not necessary, they are just there to fit with conventions of various projects and APIs that like to call pointer types by names that include P or other substrings. Sometimes these projects end up with multiple conventions over time, so there are multiple aliases. They can also be needed for compatibility reasons when APIs get updated, or between different platforms.

Array definition right after struct decalaration

An array magic is declared that is of type struct MAGIC and it consists of two elements that are immediately initialized.

The array size is not explicitly specified; it is derived from the number of initializers. An advantage is that, should you later require other (initialized) elements, you can just provide the initializer and don't need to bother about adjusting the array size specification.



Related Topics



Leave a reply



Submit