Home > OS >  How to initialize nested array of structs in C ?
How to initialize nested array of structs in C ?

Time:02-24

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.

[Demo]

#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 of unsigned char*, and
  • std::unique_ptr<Display_font_char> instead of Display_font_char*.

So you don't have to do care about memory allocations/deallocations.

[Demo]

#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;
}
  • Related