C++: how to assign static array to a pointer inside a struct - c++

I have C-code that I need to compile to C++ and need to minimally change it.
In C, the following works
typedef struct _type_t
{
int a;
int b;
int c[];
}type_t;
type_t var = {1,2,{1,2,3}};
But in C++11, it gives the error
error: too many initializers for int [0]
But I cannot give type_t.c a constant size because it needs to work for any size array.
So I need to change the struct to
typedef struct _type_t
{
int a;
int b;
int *c;
}type_t;
But then I need to change
type_t var = {1,2,{1,2,3}};
to something else because current code gives the error
error: braces around scalar initializer for type int*
Casting 3rd element to(int[]) gives error
error: taking address of temporary array
This is from micropython, parse.c:
#define DEF_RULE_NC(rule, kind, ...) static const rule_t rule_##rule = { RULE_##rule, kind, #rule, { __VA_ARGS__ } };
How do I initialize the array and assign it to type_t.c ?

Use std::vector and aggregate initialization:
struct type_t
{
int a;
int b;
std::vector<int> c;
};
int main() {
type_t var = { 1, 2, { 1, 2, 3 } };
}

In order to do this you need to make your array really static:
typedef struct _type_t
{
int a;
int b;
int * c;
}type_t;
int items[3] = {1,2,3};
type_t var = {1,2, static_cast< int * >(items)};

C++ doesn't allow this statement expression. You may use lightweight std::initialiser_list to achieve the objective
#include <initializer_list>
typedef struct _type_t
{
int a;
int b;
std::initializer_list<int> c;
}type_t;
type_t var = {1,2,{1,2,3,4}};

yet another alternative might be
...
int * c;
}type_t;
type_t var = {1,2, []{ static int x[] = {1,2,3}; return x; }() };
PS: yes, I know it's crazy, but it's somewhat more respectful of OP requirements ( it can be incorporated in a dropin replacement macro as given )

Related

can't create 2 arrays in class else incomplete type is not allowerd c++ [duplicate]

Consider the following code
struct dummy1 {
int b;
dummy1();
};
struct dummy {
dummy1 a[];
int c;
dummy();
};
int main()
{
dummy foo;
foo.a[0].b = 5;
foo.a[1].b = 6;
return 0;
}
dummy::dummy()
:a()
,c()
{
}
dummy1::dummy1()
: b()
{
}
I am getting an error "Incomplete type is not allowed" , As far as i know we get this error if the structure we are defining the object of is not defined or the header file is not included which is not the case strangely when I define my int c before a[] the code works so replacing this
struct dummy {
int c;
dummy1 a[];
dummy();
};
the code works just fine, Any ideas why this might be happening ?
P.S I am using VS2015
dummy1 a[]; is not valid. You must define the size of your array. If you don't know what size array you need in advance, use std::vector instead of a raw array:
struct dummy {
std::vector<dummy1> a;
int c;
};
int main()
{
dummy foo;
foo.a.resize(2);
foo.a[0].b = 5;
foo.a[1].b = 6;
}
The reason it compiles when you swap the order of your members is a feature of C called "flexible array members" that some compilers provide as an extension to C++. This allows you to declare an array-of-unknown-bound as the last member of a struct. No memory is reserved for that array when you declare an automatic or static variable of that type though. It's intended to be used with malloc:
struct dummy {
int c;
dummy1 a[];
};
int main() {
// allocate storage for 5 dummy1 objects in our flexible array
dummy* foo = malloc(sizeof(dummy) + 5 * sizeof(dummy1));
foo->a[0].b = 5;
foo->a[1].b = 6;
free(foo);
return 0;
}
Note that this is not a standard part of C++. It is a non-standard compiler extension, and does not play well with many C++ features. Compilers likely provide this extension mostly for compatibility with libraries written in C.
I guess it is the array a with size 0 in dummy. The standard doesn’t allow this.
Try:
struct dummy {
dummy1* a;
int c;
dummy();
};
Or:
struct dummy {
dummy1 a[1];
int c;
dummy();
};

non-const non-type expression inside template

I tried finding this one but couldn't. I am new to C++ template programming. I have a situation like this -:
#include <bits/stdc++.h>
enum DataType{
FLOAT32,
SIGNED32
:,
: (there can be other dataTypes as well)
};
struct SomeClass{
DataType d;
void* pointer;
};
void add(SomeClass a, SomeClass b)
{
DataType dataType = a.d;
using aDataType = std::conditional<dataType == FLOAT32 , float, int>;
}
int main()
{
SomeClass a;
a.d = FLOAT32;
SomeClass b;
b.d = SIGNED32;
int* p = static_cast<int*>(malloc(sizeof(int)));
*p = 4;
b.pointer = p;
float* p2 = static_cast<float*>(malloc(sizeof(float)));
*p2 = 4.3;
a.pointer = p2;
add(a, b);
return 0;
}
I want to find out the datatype of what's stored in a.pointer and b.pointer but this is giving a compile-error, saying the value of ‘dataType’ is not usable in a constant expression.
You can't use operator==, since the dataType is only known at runtime. What you are basically trying to do here is to mimic C-unions, which are quite unrelated to templates. Note, that once you receive SomeClass as a parameter, you can't really distinguish between the underlying types on compile time.
I would suggest this code:
#include <bits/stdc++.h>
template<typename T, typename U>
void add(T* a, U* b)
{
using aDataType = T; // Unnecessary, but for the example
}
int main()
{
int i = 4;
float f = 4.3;
add(&i, &f);
return 0;
}

Strange incomplete type is not allowed error

Consider the following code
struct dummy1 {
int b;
dummy1();
};
struct dummy {
dummy1 a[];
int c;
dummy();
};
int main()
{
dummy foo;
foo.a[0].b = 5;
foo.a[1].b = 6;
return 0;
}
dummy::dummy()
:a()
,c()
{
}
dummy1::dummy1()
: b()
{
}
I am getting an error "Incomplete type is not allowed" , As far as i know we get this error if the structure we are defining the object of is not defined or the header file is not included which is not the case strangely when I define my int c before a[] the code works so replacing this
struct dummy {
int c;
dummy1 a[];
dummy();
};
the code works just fine, Any ideas why this might be happening ?
P.S I am using VS2015
dummy1 a[]; is not valid. You must define the size of your array. If you don't know what size array you need in advance, use std::vector instead of a raw array:
struct dummy {
std::vector<dummy1> a;
int c;
};
int main()
{
dummy foo;
foo.a.resize(2);
foo.a[0].b = 5;
foo.a[1].b = 6;
}
The reason it compiles when you swap the order of your members is a feature of C called "flexible array members" that some compilers provide as an extension to C++. This allows you to declare an array-of-unknown-bound as the last member of a struct. No memory is reserved for that array when you declare an automatic or static variable of that type though. It's intended to be used with malloc:
struct dummy {
int c;
dummy1 a[];
};
int main() {
// allocate storage for 5 dummy1 objects in our flexible array
dummy* foo = malloc(sizeof(dummy) + 5 * sizeof(dummy1));
foo->a[0].b = 5;
foo->a[1].b = 6;
free(foo);
return 0;
}
Note that this is not a standard part of C++. It is a non-standard compiler extension, and does not play well with many C++ features. Compilers likely provide this extension mostly for compatibility with libraries written in C.
I guess it is the array a with size 0 in dummy. The standard doesn’t allow this.
Try:
struct dummy {
dummy1* a;
int c;
dummy();
};
Or:
struct dummy {
dummy1 a[1];
int c;
dummy();
};

How to use anonymous struct or class?

So, it's possible to declalre anonymous class or struct but how to I make it useful?
int main() {
class{
int ClassVal;
};
struct{
short StructVal;
};
StructVal = 5; //StructVal is undefined
ClassVal = 5; //ClassVal is undefined too?
return 0;
}
if you put both of them outside of main function they will be inaccessible as well.
I'm asking this only because it's somehow intersting :)
EDIT:
Why union outside of main function (at global scope) must be static declared
for example:
static struct {
int x;
};
int main() {
//...
}
Anonymous classes and structures may be used to directly define a variable:
int main()
{
class
{
int ClassVal;
} classVar;
struct
{
short StructVal;
} structVar;
structVar.StructVal = 5;
classVar.ClassVal = 5;
return 0;
}
The above is not very common like that, but very common when used in unions as described by Simon Richter in his answer.
These are most useful in the form of nested struct and union:
struct typed_data {
enum type t;
union {
int i; // simple value
struct {
union { // any of these need a length as well
char *cp;
unsigned char *ucp;
wchar_t *wcp;
};
unsigned int len;
};
};
};
Now typed_data is declared as a type with the members t, i, cp, ucp, wcp and len, with minimal storage requirements for its intended use.

How to use a struct inside another struct?

I want to use a nested structure, but I don't know how to enter data in it. For example:
struct A {
int data;
struct B;
};
struct B {
int number;
};
So in main() when I come to use it:
int main() {
A stage;
stage.B.number;
}
Is that right? If not how do I use it?
Each member variable of a struct generally has a name and a type. In your code, the first member of A has type int and name data. The second member only has a type. You need to give it a name. Let's say b:
struct A {
int data;
B b;
};
To do that, the compiler needs to already know what B is, so declare that struct before you declare A.
To access a nested member, refer to each member along the path by name, separated by .:
A stage;
stage.b.number = 5;
struct A {
struct B {
int number;
};
B b;
int data;
};
int main() {
A a;
a.b.number;
a.data;
}
struct B { // <-- declare before
int number;
};
struct A {
int data;
B b; // <--- declare data member of `B`
};
Now you can use it as,
stage.b.number;
The struct B within A must have a name of some sort so you can reference it:
struct B {
int number;
};
struct A {
int data;
struct B myB;
};
:
struct A myA;
myA.myB.number = 42;
struct A
{
int data;
struct B
{
int number;
}b;
};
int main()
{
A stage = { 42, {100} };
assert(stage.data == 42);
assert(stage.b.number == 100);
}
struct TestStruct {
short Var1;
float Var2;
char Var3;
struct TestStruct2 {
char myType;
CString myTitle;
TestStruct2(char b1,CString b2):myType(b1), myTitle(b2){}
};
std::vector<TestStruct2> testStruct2;
TestStruct(short a1,float a2,char a3): Var1(a1), Var2(a2), Var3(a3) {
testStruct2.push_back(TestStruct2(0,"Test Title"));
testStruct2.push_back(TestStruct2(4,"Test2 Title"));
}
};
std::vector<TestStruct> testStruct;
//push smthng to vec later and call
testStruct.push_back(TestStruct(10,55.5,100));
TRACE("myTest:%s\n",testStruct[0].testStruct2[1].myTitle);
I have somewhat like the following code running for a while live now and it works.
// define a timer
struct lightTimer {
unsigned long time; // time in seconds since midnight so range is 0-86400
byte percentage; // in percentage so range is 0-100
};
// define a list of timers
struct lightTable {
lightTimer timer[50];
int otherVar;
};
// and make 5 instances
struct lightTable channel[5]; //all channels are now memory allocated
#zx485: EDIT: Edited/cleaned the code. Excuse for the raw dump.
Explanation:
Define a lightTimer. Basically a struct that contains 2 vars.
struct lightTimer {
Define a lightTable. First element is a lightTimer.
struct lightTable {
Make an actual (named) instance:
struct lightTable channel[5];
We now have 5 channels with 50 timers.
Access like:
channel[5].timer[10].time = 86400;
channel[5].timer[10].percentage = 50;
channel[2].otherVar = 50000;