Получение указателя типа примитива в функции - PullRequest
0 голосов
/ 25 августа 2018

У меня есть объединение (ValueDefinition) с указателями различных типов данных и функциями для его создания.С String все работает нормально:

ValueDefinition CreateValDefString(String value){
        ValueDefinition valDef = {.ValueString = new String(value)};
        return valDef;
    }

Но когда я делаю то же самое, например, с uint8_t, он компилируется, но во время выполнения я получаю эту ошибку:

[E][WString.cpp:185] changeBuffer(): realloc failed! Buffer unchanged

Это код для uint8_t:

ValueDefinition CreateValDefUint8(uint8_t value){
    ValueDefinition valDef = {.ValueUInt8 = new uint8_t(value)};
    return valDef;
}

Что я делаю не так?Я попробовал это без «new» и с malloc, но все равно получаю ту же ошибку.

Редактировать: По запросу, определение ValueDefinition:

 union ValueDefinition{
     bool* ValueBool;
     int8_t* ValueInt8;
     int16_t* ValueInt16;
     int32_t* ValueInt32;
     uint8_t* ValueUInt8;
     uint16_t* ValueUInt16;
     uint32_t* ValueUInt32;
     float* ValueFloat;     
     ulong* ValueULong;
     String* ValueString;
 };

1 Ответ

0 голосов
/ 25 августа 2018

В вашем коде похоже, что C ++ выдает ошибку в функцию, чтобы создать WString вместо uint8_t, следовательно, трассировка стека в совершенно отдельном заголовке. Поиск исходного кода в хранилище для arduino показывает, что в WString.cpp здесь есть ошибка, которую обнаруживает ваш компилятор.

Пользователи github предлагают использовать другую библиотеку строк, и поскольку ошибка не была исправлена, вам придется изменить ее, возможно, на стандартную библиотеку string, определенную в C ++ и , а не arduino. Как заявили пользователи на github, строки arduino общеизвестно ненадежны.

Другими словами, эта ошибка не имеет ничего общего с вашим кодом, но я хотел бы задать вопрос: «Зачем использовать объединения в C ++?» Если вы хотите определить универсальный тип, просто используйте угловые скобки в объявлении типа, например:

 class ValueDefinition<T> {
 private:
     T typeDat;
 public:
     Valuedefinition<T>(T t);
     /* etc. */
 }

Объединения были сделаны таким образом, чтобы C мог использовать универсальную типизацию, используя несколько типов, совместно использующих данные в объединении. Другое распространенное использование - использование типов данных, использующих одну и ту же память, чтобы найти базовый двоичный файл более сложных типов, например использование отдельных значений uint8_t, лежащих в основе long long, для поиска значения его битов, или использование int чтобы получить двоичное значение float, например:

union foo {
   uint8_t bits[4]; /* Represent the bits of 'data' */

   long long int data;
}

union foo myLong = {.data = 12378591249169278l};
printf("%d\n", myLong.bits[0]); // Returns the value of the high bit of myLong

Однако обратите внимание, что это неопределенное поведение , потому что союзы обычно дополняются , поэтому не пытайтесь делать это в любом случае. Что бы вы ни делали, если вы используете C ++, есть лучшее решение, чем использование союзов, так как это была функция, предназначенная для языка, который не имел универсальной типизации для экономии памяти .

Edit: Инициализируйте ValueDefinition следующим образом, используя управление памятью в стиле C:

union ValueDefinition *value = malloc(sizeof(union ValueDefinition));
value->ValueUInt8 = malloc(sizeof(uint8_t));
/* more code */

Или с C ++ new:

union ValueDefinition *value = new ValueDefinition();
value->ValueUInt8 = new uint8_t(/* Some number */);
/* more code */
...