I have the following definitions:
struct Display_font_char
{
unsigned char * data;
int originX;
int originY;
unsigned int width;
unsigned int height;
unsigned int delta;
};
struct Display_font
{
Display_font_char * chars;
unsigned char rangeStart;
unsigned char rangeEnd;
};
How can I initialize it inplace? I'm trying:
const Display_font font =
{
{
{
{ 1, 2, 3 },
1,
2,
3u,
4u,
5u
}
},
1u,
2u
}
However, I'm getting an error: "Cannot use value of type int to initialize field of type Display_font_char *"
CodePudding user response:
You cannot initialise a pointer with a braced init list of multiple values.
Here is an example of how you could initialise an instance of the class:
unsigned char uc[] = { 1, 2, 3 };
Display_font_char fc {
uc,
1,
2,
3u,
4u,
5u,
};
const Display_font font =
{
&fc,
1u,
2u,
};
As a sidenote, if you were to switch to C, then you could use compound literals:
const struct Display_font font =
{
&(struct Display_font_char){
(unsigned char []){ 1, 2, 3 },
1,
2,
3u,
4u,
5u
},
1u,
2u
};
But alas, compound literals don't exist in C .
CodePudding user response:
In order to initialize your pointers, you have to create the pointed structures first, for example using new
.
Notice that, if you want to keep an unsigned char*
array in Display_font_char
, you should need to know its size (e.g. through a size_t data_size
member).
In the example below I create the structs with new
and I use data
as an array of chars, so I can easily print it.
#include <iostream> // cout
#include <ostream>
#include <vector>
struct Display_font_char
{
unsigned char* data;
int originX;
int originY;
unsigned int width;
unsigned int height;
unsigned int delta;
};
std::ostream& operator<<(std::ostream& os, const Display_font_char& f)
{
os << "\tdata = " << f.data << "\n";
os << "\toriginX = " << f.originX << "\n";
os << "\toriginY = " << f.originY << "\n";
os << "\twidth = " << f.width << "\n";
os << "\theight = " << f.height << "\n";
os << "\tdelta = " << f.delta << "\n";
return os;
}
struct Display_font
{
Display_font_char* chars;
unsigned char rangeStart;
unsigned char rangeEnd;
};
std::ostream& operator<<(std::ostream& os, const Display_font& f)
{
os << "chars =\n" << *f.chars << "\n";
os << "rangeStart = " << f.rangeStart << "\n";
os << "rangeEnd = " << f.rangeEnd << "\n";
return os;
}
int main()
{
const Display_font font = {
new Display_font_char{new unsigned char[4]{'1', '2', '3', 0}, 1, 2, 3u, 4u, 5u},
'1',
'2'
};
std::cout << font;
}
This other version uses:
std::vector
instead ofunsigned char*
, andstd::unique_ptr<Display_font_char>
instead ofDisplay_font_char*
.
So you don't have to do care about memory allocations/deallocations.
#include <iostream> // cout
#include <memory> // make_unique, unique_ptr
#include <ostream>
#include <vector>
struct Display_font_char
{
std::vector<unsigned char> data;
int originX;
int originY;
unsigned int width;
unsigned int height;
unsigned int delta;
};
std::ostream& operator<<(std::ostream& os, const Display_font_char& f)
{
os << "\tdata = [";
bool first{true};
for (auto& d : f.data)
{
os << (first ? "" : ", ") << static_cast<int>(d);
first = false;
}
os << "]\n";
os << "\toriginX = " << f.originX << "\n";
os << "\toriginY = " << f.originY << "\n";
os << "\twidth = " << f.width << "\n";
os << "\theight = " << f.height << "\n";
os << "\tdelta = " << f.delta << "\n";
return os;
}
struct Display_font
{
std::unique_ptr<Display_font_char> chars;
unsigned char rangeStart;
unsigned char rangeEnd;
};
std::ostream& operator<<(std::ostream& os, const Display_font& f)
{
os << "chars =\n" << *(f.chars.get()) << "\n";
os << "rangeStart = " << static_cast<int>(f.rangeStart) << "\n";
os << "rangeEnd = " << static_cast<int>(f.rangeEnd) << "\n";
return os;
}
int main()
{
const Display_font font{
std::make_unique<Display_font_char>(
std::vector<unsigned char>{1, 2, 3}, 1, 2, 3u, 4u, 5u),
1,
2
};
std::cout << font;
}