Colon : used in variable initialization? [duplicate] - c++

This question already has answers here:
What does a colon in a struct declaration mean, such as :1, :7, :16, or :32?
(3 answers)
Closed 7 years ago.
I found this line here:
uint32 bIsHungry : 1;
... and I've never seen this syntax used to initialize a variable.
I'm used to seeing this:
uint32 bIsHungry = 1;
It looks kind of like an initialization list, but for a single field?
What is it, what does it do, why should I care?

That line is a bit field declaration and it declares a data member with an explicit bit-level size
Example from cppreference:
#include <iostream>
struct S {
// three-bit unsigned field,
// allowed values are 0...7
unsigned int b : 3;
};
int main()
{
S s = {7};
++s.b; // unsigned overflow
std::cout << s.b << '\n'; // output: 0
}
Notice that in the example above the unsigned overflow is defined behavior (same doesn't apply if b were declared as a signed type)
The documentation you links also states that
Boolean types can be represented either with the C++ bool keyword or as a bitfield
Regarding why should I care I recommend reading this other question

It is not initialization, it is a fragment of a declaration.
struct {
// ...
uint32 bIsHungry : 1;
// ...
};
declares a bIsHungry as a bitfield member of the struct. It says that bIsHungry is an unsigned int whose length is 1 bit. Its possible values are 0 and 1.
Read more about bitfields: http://en.cppreference.com/w/c/language/bit_field

This is bitfield declaration, Declares a class data member with explicit size, in bits.

Related

C++ object looks like its being used as struct [duplicate]

This question already has answers here:
What is the use of Struct Tag name in C programming?
(3 answers)
What are the advantages of differentiating type/tag names for a typedef in C?
(3 answers)
Does typedef of a structure without tag creates distinct type each time it is used and if not why?
(2 answers)
Closed 6 months ago.
In the following code, I thought saCmdQueue_s is a struct and saCmdQueue_t is an object of type saCmdQueue_s. But then I see the last line looks like they are using saCmdQueue_t to set the type for an object named sa_queue[SA_QSIZE]. Can some help me understand.
typedef struct saCmdQueue_s {
uint8_t *buf;
int len;
} saCmdQueue_t;
#define SA_QSIZE 6 // 1 heartbeat (GetSettings) + 2 commands + 1 slack
static saCmdQueue_t sa_queue[SA_QSIZE];
In C++, when struct is declared, usage is different according to declare type.
If struct is declared as typedef type, you can write other name at the end of struct. Other name is the new name of the type - struct you declared.
Otherwise, if struct is declared as usual type, the result is the following.
struct saCmdQueue_s {
uint8_t* buf;
int len;
} saCmdQueue_t;
#define SA_QSIZE 6 // 1 heartbeat (GetSettings) + 2 commands + 1 slack
saCmdQueue_t sa_queue[SA_QSIZE];
Error: variable "saCmdQueue_t" is not a type name
If you write typedef in front of struct, the struct is declared the type like data type(int, char, string, vector, ...).

C++ - Get "id" of class's variable from enum class [duplicate]

This question already has an answer here:
c++ enum class integer not working for array subscript
(1 answer)
Closed 2 years ago.
If I have code:
class A {
public:
int x;
enum class nums {
Ab = 0,
Bc,
Cd,
De,
Ef
};
A() { this->x = 0; }
}Avar [5];
Is somehow possible to use enum nums numbers as "id" for class's variable Avar[], so I don't need to converting to int with static_cast<> or int()?
if (Avar[static_cast<int>(A::nums::Cd)].x == 10) {
Something like Avar[A::nums::Cd].x ?
An enum class (aka scoped enumeration) is not implicitly convertible to an integer and cannot thus be used as an index of an array without a cast. You can use a plain enum instead of an enum class. Unlike enum classes, an enum is implicitly convertible to an integer and can therefore be used as an index of an array.
P.S. Don't use a magic number for the size of the array. Use an extra enum value that will have the size:
enum nums {
Ab = 0,
Bc,
Cd,
De,
Ef,
nums_count,
};
...
}Avar [A::nums_count];

I'm trying to understand [class.bit]/1, but I found this strange behavior

Consider this snippet:
#include<iostream>
struct S {
int bf1:16, bf2:7;
char bf3:8;
} s;
struct A{
int i;
char c;
};
int main() {
std::cout << sizeof(S) << '\n';
std::cout << sizeof(A) << '\n';
}
clang and GCC print the following values for the code above (see live example):
4
8
That is, it allocates the bit-field bf3 as if I had defined struct S as follows:
struct S{
int bf1:16, bf2:7, bf3:8
};
That doesn't seem to be correct.
Note also, that if I define the bit-field bf3 with 9 bits, in the original snippet, both compilers emit a warning saying that the 9 bits exceed the width of its type, a char, but now they print 8 bytes for the struct S. That's strange, as it's still possible to allocate the 9 bits, as if bf3 was declared in the first int member of the struct.
I know the Standard says in [class.bit]/1 that:
Allocation of bit-fields within a class object is
implementation-defined.
Maybe I'm missing something, but I think there is some inconsistency in the way both compilers are treating this case.

Correct and simplest syntactical way to initialise an array to 0 [duplicate]

This question already has answers here:
How to initialize all members of an array to the same value?
(26 answers)
Closed 8 years ago.
I am trying to find out the correct way to initialise an array to all zeros (i.e. as if you have done a memset on the array).
I have found the following methods from various areas in stack overflow (and other sources):
char myArray1[10] = {0};
char myArray2[10] = {0,};
char myArray3[10] = {[0 ... 9] = 0};
char myArray4[10] = {0,0,0,0,0,0,0,0,0,0};
I would prefer the simplest syntax variant... I was using {0}, but I have not found any proof this actually is correct.
Missing elements in an array will be initialised to 0. In addition, C++ allows you to leave the uniform initialiser empty. So the following works, is minimal and also the most efficient:
T array[N] = {};
It’s worth noting that this works for any type T which can be either default-constructed or initialised, not just built-in types. For example, the following works, and will print foo five times:
#include <iostream>
struct foo {
foo() { std::cout << "foo()\n"; }
};
int main() {
foo arr[5] = {};
}
A more extensive list of the different possibilities was posted by aib some time ago.
From the C++ specification, "Aggregate initialization" (8.5.1):
If there are fewer initializer-clauses in the list than there are members in the aggregate, then each member not explicitly initialized shall be initialized from an empty initializer list.
So each char not in the initializer list would be initialized to char() that is 0.
In C++11 you can type:
char a[10] = {};
char b[10]{};
Some old compilers (or was it in C) may require you add at least one member:
char a[10] = {0};
Naturally, if the array has static lifetime (global or static variable), then it will be zero initialized if there is not initializer:
char global_array[10];
I find it confusing, so I prefer to add the = {} anyway.
About the trailing comma, it is useful if you do something like:
char a[] = {
1,
2,
3,
};
So that you don't make a special case for the last line and you make copy&paste and diffs easier. In your specific case is just useless:
char a[10] = {0,};
That comma does nothing, and it is ugly, so I wouldn't write it.
I prefer this because it is simple yet explicit:
char myArray1[10] = { 0 };

C/C++: size of a typedef struct containing an int and enum == sizeof(int)?

I am using gcc version 4.3.3 on my Ubuntu (i686). I have written a stripped down test program to describe my lack of understanding and my problem. The program shall tell me the size of the struct, which I implemented. So I have a typedef struct for a Message and a little main to play around:
#include <stdio.h>
typedef struct {
int size;
enum {token=0x123456};
} Message;
int main(int argc, char * argv[])
{
Message m;
m.size = 30;
printf("sizeof(int): %d\n",sizeof(int));
printf("sizeof(0x123456): %d\n",sizeof(0x123456));
printf("sizeof(Message): %d\n",sizeof(Message));
printf("sizeof(m): %d\n",sizeof(m));
}
While compiling this source with gcc I get the following warning, which I don't understand:
$ gcc sizeof.c
sizeof.c:5: warning: declaration does not declare anything
Line 5 refers to the enum line. I want that token in every Message, that I create. What am I doing wrong? What do I have to change to get rid of that warning?
My main contains several calls of sizeof(). When I run the program, you can see in the output that the integer has the size of four, the hex number has the size of 4, but the typedef struct Message has the size of 4, too:
$ ./a.out
sizeof(int): 4
sizeof(0x123456): 4
sizeof(Message): 4
sizeof(m): 4
That is very confusing to me. Why has Message the size of 4, although it contains an integer and an integer within an enum, each with the size of 4. If the sizeof(Message) would be at least 8, it would be logical to me.
But why is it only 4? How do I get the real size in Bytes of my Message? Or is this really the real size? If so, why?
Is there a difference in getting the size of a Message between C and C++?
An enumeration doesn't actually need any space, it's just a way for the compiler to recognize a set of literal numbers by a name.
You are not declaring anything with:
enum {token=0x123456};
Your declaration is similar to:
typedef struct {
int size;
int;
} Message;
If you declare your struct like this:
typedef struct {
int size;
enum {token=0x123456} e;
} Message;
There will be two fields, but e will not be initialized to anything. You need to set it manually for every instance: message.e=token.
The correct way to achieve what you want is, to use constructors in C++:
struct Message {
int size;
int token;
Message() : token(0x123456) {};
};
Or non-static data member initializers in C++11:
struct Message {
int size;
int token=0x123456;
};
There is no way to initialize field in struct declaration in C.
Line 5 does not declare any variable that is of type enum. So the compiler does the only thing it can do: ignore it.
If you want to create a member of that type in the struct, write something like
enum {token=0x123456} thetoken;
But be aware that this field can only have one valid value, is that what you want?
Edit:
Oh, and to answer your other question: I can't see a difference in output when compiling as C or C++. But there is a difference between how how you should write struct definitions.
typedef struct {
int size;
enum YouShouldDeclareAName {token=0x123456};
} Message;
your enum is a subclass/subtype of your Message struct, therefore bounds to Class and not object. Like a namespace. You do not create any variable with it.
Change it to:
typedef struct {
int size;
enum YouShouldDeclareAName {token=0x123456} token;
//or
YouShouldDeclareAName token2;
} Message;
You've defined a constant Message::token that's shared between all objects. Since it's shared, it doesn't count towards the size of a single object.
As the others answers note, you've declared an enumerated type, you just happened to do it inside a structure instead of at global scope. There's nothing to store, so it uses no memory.
Now if you were to declare an instance of your enumeration in that structure...
typedef struct {
int size;
enum {token=0x123456} e;
} Message;
int main(int argc, char * argv[])
{
Message m;
m.size = 30;
printf("sizeof(m): %d\n",sizeof(m));
}
sizeof(m): 8
Press any key to continue . . .
LINE 5:
enum {token=0x123456};
This line doesn't define any enum variable, its a declaration, because of this your compiler complains about line 5 saying its only a declaration.
proper usage should be:
enum {xyz=5} enum_variable_name;
Only then the compiler will allocate space for this.
Just like class, function, enum, static menber doesn't store in the object space!