包含char数组数组的结构

时间:2019-01-16 07:58:32

标签: c++ arduino flexible-array-member

我正在尝试定义一个结构实例,并且在设置此变量时遇到了特别麻烦。这是一个char数组的数组。

这是我的头文件中的结构...

struct widget_t {
    char *name;
    uint8_t numberOfNicknames;
    char *nicknames[];
};

这是我试图设置widget_t结构的实例...

widget_t SomeWidget;

void setUpFunction () {
    SomeWidget.name = (char *)"Lawn Mower";
    SomeWidget.numberOfNicknames = 2;
    SomeWidget.nicknames = {
        "Choppie McGrasschopper",
        "Really Noisy"
    };
}

因此,当我尝试将昵称放入SomeWidget.nicknames时,发生了错误。我不确定是否需要做一些时髦的事情,例如将name用作指针...?

棘手的是,nicknames的数目是可变的。因此,每个实例都希望设置不同数量的对象。

4 个答案:

答案 0 :(得分:1)

您遇到的问题是 c ++ 不支持变量数组。相反,您将必须使用 new 或在您的情况下 new [] 动态分配内存。

首先,您需要将数据类型更改为char**,几乎等于之前的数据类型。然后,您可以像nicknames = new char*[number_of_nicknames]这样分配任意数量的字符串。

重要的是,使用这种方法,您将必须手动删除昵称,例如:delete[] nicknames;。最好的方法是使用RAII(在解构函数中删除昵称)

具有动态字符串时,您将使用以下结构

struct widget_t {
    // optional constructor to allocate nicknames

    ~widget_t()
    {
        for (int i = 0; i < numberOfNicknames; ++i)
        {
            char* nickname = nicknames[i];

            if (nickname)
                delete[] nickname;
        }

        delete[] nicknames;
    }

    char *name;
    uint8_t numberOfNicknames;
    char **nicknames = NULL;
};

下一个带有常量字符串

struct widget_t {
    // optional constructor to allocate nicknames
    // allocate nicknames like
    // -> nicknames = new const char*[numberOfNicknames];

    ~widget_t()
    {
         if (nicknames) delete[] nicknames;
    }

    char *name;
    uint8_t numberOfNicknames;
    const char **nicknames = NULL;
};

答案 1 :(得分:0)

您要尝试的是将字符串文字分配给char *指针-这很糟糕(请参阅How to get rid of deprecated conversion from string constant to ‘char*’ warnings in GCC?中的更多信息)。这是一种可能的方法:

#define MAX_NAME_LEN 128
#define MAX_NICK_NAMES 10

struct widget_t {
    char name[MAX_NAME_LEN];
    uint8_t numberOfNicknames;
    char nicknames[MAX_NICK_NAMES][MAX_NAME_LEN];
};

widget_t SomeWidget;

void setUpFunction () {
    strcpy(SomeWidget.name, "Lawn Mower");
    SomeWidget.numberOfNicknames = 2;
    strcpy(SomeWidget.nicknames[0], "Choppie McGrasschopper");
    strcpy(SomeWidget.nicknames[1], "Really Noisy");
}

无论如何,由于您用C++标记了问题,因此建议您改用std::stringstd::vector

答案 2 :(得分:0)

一个选择是:

struct widget_t {
    char const *name;
    uint8_t numberOfNicknames;
    char const * const *nicknames;
};

static char const *mower_nicknames[] = { "Choppie", "Bob" };
widget_t SomeWidget = { "Lawn Mower", 2, mower_nicknames };

static char const *bus_nicknames[] = { "Wheels", "Go", "Round" };
widget_t OtherWidget = { "Bus", 3, bus_nicknames };

// no setup function needed

答案 3 :(得分:0)

这里有不同的问题。

您的最后一个成员的类型不完整,因为它是未声明维的数组。这在C ++中是不允许的,但是大多数编译器都允许它作为具有与C相同语义的扩展。无论如何,这都是相当棘手的,因为它只能与已分配的结构一起使用,在该结构中,您为结构本身不完整的数组。

接下来,您要尝试分配一个数组。你不能。数组不是C ++(也不是C)中的第一类对象。您可以将数组整体初始化,但只能分配给数组元素。

最后,您要向char *分配C字母字符串。这很不好,因为标准声明垃圾字符串为const,因此以后使用指针更改字符将为未定义行为。如果您不这样做,它将起作用,但是指针至少应声明为const

这是您可以使用所有这些内容的方式:

widget_t* setUpFunction () {
    // allocates a widget_t with 2 slots in nicknames
    widget_t *someWidget = (widget_t *) malloc(sizeof(widget_t) + 2 * sizeof(char *));
    someWidget.name = (char *)"Lawn Mower";   // VERY DANGEROUS: pointer should be const
    someWidget.numberOfNicknames = 2;
    someWidget.nicknames[0] = (char *) "Choppie McGrasschopper"; // SAME DANGER
    someWidget.nicknames[1] = (char *) "Really Noisy"            // Still same danger
    return widget_t;
}

但是所有这一切都是相当C的,应该在C ++中避免。此外,它仍然需要分配的内存,这可能不是您想要的Arduino