Warning: file_get_contents(/data/phpspider/zhask/data//catemap/7/arduino/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 包含字符数组数组的结构_C++_Arduino_Flexible Array Member - Fatal编程技术网

C++ 包含字符数组数组的结构

C++ 包含字符数组数组的结构,c++,arduino,flexible-array-member,C++,Arduino,Flexible Array Member,我试图定义一个结构的实例,但在设置这个变量时遇到了特殊的问题。这是一个字符数组 这是我的头文件中的结构 struct widget_t { char *name; uint8_t numberOfNicknames; char *nicknames[]; }; 我正在尝试设置widget\u tstruct的实例 widget_t SomeWidget; void setUpFunction () { SomeWidget.name = (char *)"La

我试图定义一个结构的实例,但在设置这个变量时遇到了特殊的问题。这是一个字符数组

这是我的头文件中的结构

struct widget_t {
    char *name;
    uint8_t numberOfNicknames;
    char *nicknames[];
};
我正在尝试设置
widget\u t
struct的实例

widget_t SomeWidget;

void setUpFunction () {
    SomeWidget.name = (char *)"Lawn Mower";
    SomeWidget.numberOfNicknames = 2;
    SomeWidget.nicknames = {
        "Choppie McGrasschopper",
        "Really Noisy"
    };
}
因此,当我尝试将昵称放入
SomeWidget.昵称
时,就会发生错误。我不确定我是否需要做一些时髦的事情,比如我正在做的
name
作为指针


棘手的是,
昵称的数量是可变的。因此,每个实例都需要设置不同数量的指针。

您试图做的是为
char*
指针分配一个字符串文字,这是不好的(请参阅中的详细信息)。以下是一种可能的方法:

#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::string
std::vector

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

首先,您需要将数据类型更改为
char**
,几乎与之前的数据类型相同。然后,您可以分配任意数量的字符串,如下所示
昵称=新字符*[number\u of\u昵称]

重要的是,使用此方法,您必须像下面这样手动删除您的昵称:
delete[]昵称。实现这一点的最佳方法是使用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 {
    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

这里有不同的问题

首先是中的最后一个成员的类型不完整,因为它是一个未声明维度的数组。这在C++中是不允许的,但是大多数编译器允许它作为与C相同的语义扩展。无论如何,这是相当棘手的,因为它只能用于分配的结构,在这里为结构本身分配内存<强>和<强>不完整数组。 接下来,您将尝试分配给数组。你不能。数组不是C++中的第一类对象(也不是C)。可以将数组作为一个整体进行初始化,但只能指定给数组元素

最后,将一个C字符串分配给一个
char*
。这是不好的,因为标准声明literal字符串是
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++中使用。另外,它仍然需要分配的内存,这可能不是您想要的ARDIONI/P>,即使C++没有灵活的数组成员,编译器也提供了一个扩展,几乎遵循C语义。这意味着,尽管标签不匹配,但这个问答几乎是重复的。他还用arduino标记了他的答案,所以你最后的建议是不可能的。@Phins arduino有STL端口。@DanM。但这不是一个好的选择,STL是为不同的平台优化的。@duong_dajgja改变了,我认为RAII适合这个用途。注意:这不是VLA,而是不完整的类型。在C.,它们是不同的动物和不同的语义,但两者都没有被C++标准所规定。
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;
}