Помощь - Поиск - Пользователи - Календарь
Полная версия этой страницы: Инициализация структур
Форум разработчиков электроники ELECTRONIX.ru > Сайт и форум > В помощь начинающему > Программирование
kolobochishe
Добрый день sm.gif

Есть такая проблема при разработке программ: пишешь, пишешь, а потом надо вдруг добавить какое-то поле к структуре. И если например:

Код
typedef struct {
int Number;
float Value;
} Struct1;


вдруг поменялось на

Код
typedef struct {
float Percent;
int Number;
float Value;
} Struct1;


то все структуры инициализированные

Код
Struct1 structElement = { 1, 0.56 };


будут совсем даже неправильно заполненными. То что в дополнительном поле, которое появилось, будет 0 меня не интересует, это допустимо

Т.е. получается только инициализация отдельно по полям? И никаких структур-констант, если хочешь чтобы все было четко по полям?
Код
void SetStruct1 ( void )
{
   structElement.Number = 1;
   structElement.Value = 0.56;
}
aaarrr
Если компилятор поддерживает C99, то можно делать так:
Код
Struct1 structElement =
{
    .Number = 1,
    .Value = 0.56
}
kolobochishe
Цитата(aaarrr @ Nov 25 2015, 19:48) *
Если компилятор поддерживает C99, то можно делать так:
Код
Struct1 structElement =
{
    .Number = 1,
    .Value = 0.56
}



cheers.gif Отлично! Все нормально, VisualDSP 5.1 поддерживает.
esaulenka
Цитата(aaarrr @ Nov 25 2015, 17:48) *
можно делать так:


Вот интересно, почему в C++ это не добавили?
Т.е. gcc умеет, но в нарушение стандарта...
CrimsonPig
Цитата(esaulenka @ Nov 25 2015, 15:58) *
Вот интересно, почему в C++ это не добавили?
Т.е. gcc умеет, но в нарушение стандарта...


напишите структуре конструктор, делов-то..
esaulenka
Спасибо!
... и почему я об этом не подумал?..

Только оно
а) будет ли работать с глобальной const TStruct my_struct ?
б) неудобно, если надо несколько экземпляров структуры (у конструктора тоже могут быть параметры, но это возврат к той же проблеме - десяток полей малопонятным списком). Отнаследовать от одной структуры пяток разных, переопределить конструкторы - вариант, конечно, но как-то через ж., мне кажется.
_Pasha
самый нормальный вариант инициализации структур - не через имена полей а через макрос.
единожды переопределенный макрос не позволит пропустить неотредактированный остальной текст.
psL
Цитата(esaulenka @ Nov 25 2015, 18:58) *
Вот интересно, почему в C++ это не добавили?
Т.е. gcc умеет, но в нарушение стандарта...

C++ 11 разве не умеет?
esaulenka
Цитата(psL @ Nov 26 2015, 11:23) *
C++ 11 разве не умеет?

Тот, что в стандарте - нет.

Вот тут http://stackoverflow.com/questions/6181715...-initialisation тему обсуждали со всех возможных сторон. Красивого решения, к сожалению, не нашли...


PS а вообще, надо б в эклипс написать feature request, чтоб в парсере кода добавили поддержку, и пользоваться вариантом из C99 в коде С++. Один фиг gcc это умеет, а задачей "писать код под все компиляторы разом" я не заморачивался; подозреваю, там будет куда больше проблем, чем эти структуры.


Вот, кстати, в процессе нашёл интересное описание расширений gcc: https://gcc.gnu.org/onlinedocs/gcc/Designated-Inits.html
sigmaN
В конструкторе есть такая штука как список инициализаци. Ну т.е. constructor(): field1(255), field2(32.5){};

Прелесть такого подхода в том, что если переменная(с типом нашей структуры с хитрым конструктором) имеет static storage duration и класс удовлетворяет требованиям standard layout то инициализация будет выполнена статически и не потребует накладных расходов в рантайме. Т.е. Байты будут разложены по полочкам еще на этапе выполнения startup.

Уж не знаю на сколько это по стандарту, но на практике это подтверждено ни раз и не два. Написанное же в теле конструктора - не всегда разруливалось статически. Так что всегда стараюсь для инициализации использовать именно вышеописанный вариант.
Atlantis-
Прошу прощения за небольшой оффтоп, не хочется новую тему создавать.
Наверное, глупый вопрос, но точный ответ на него нигде не нашел.
Если сравнивать по быстродействию, будет ли отличие, если я меняю значение переменной (или массива) и меняю значение элемента структуры?
Грубо, говоря, вот это выполняется за одинаковое количество тактов?
Код
buff[0] =1;

и
Код
Struct.buff[0] =1;

AnatolyT
Если переменные массив и структура одного типа, обе глобальные или обе локальные, то как правило обращение к ним сформированное компилятором одинаковое, место массива в структуре компилятор рассчитает сам. Проверить несложно, откомпилируйте в asm.
zltigo
QUOTE (Atlantis- @ Dec 9 2015, 18:37) *
Если сравнивать по быстродействию, будет ли отличие, если я меняю значение переменной (или массива) и меняю значение элемента структуры?

Либо АБСОЛЮТНО одинаково, либо работа со структурой дает выигрыш в общем случае, когда рядом идет работа и с другими элеменами этой структуры.
Исключения могут только быть, по понятной причине, при работе с пакованной структурой.
Atlantis-
Спасибо, что развеяли мои сомнения.
Получается выгодно и красиво заворачивать кольцевой буфер и его элементы в структуру. И легко потом понять в программе, что относится к кольцевому буферу, а что нет
Сергей Борщ
Разумеется. А еще лучше перейти на C++ и завернуть в класс.
Genadi Zawidowski
Я для контроля ошибок в таких случаях (когда меняется набор полей структуры) добавляю последним поле, инициализированное например указателем на символ - "label" - часто помогает.
Atlantis-
Цитата(Сергей Борщ @ Dec 10 2015, 00:43) *
Разумеется. А еще лучше перейти на C++ и завернуть в класс.

А нельзя еще в структуре константы прописать? Размер буфера и маску?
Структура в памяти линейно располагается, а если в ней объявить константу с ключевым словом const ?
CrimsonPig
Цитата(Atlantis- @ Dec 10 2015, 12:12) *
А нельзя еще в структуре константы прописать? Размер буфера и маску?
Структура в памяти линейно располагается, а если в ней объявить константу с ключевым словом const ?


Конечно можно! Вот так, например:
CODE
struct TMyStruct
{
static const uint32 Const1 = 12;

//-- interger "constants" only
enum TSome
{
EItem1 = 0,
EItem2 = 13,
};

};


Компилятор, правда, нужен правильный sm.gif
Atlantis-
Цитата(CrimsonPig @ Dec 10 2015, 15:27) *
Конечно можно! Вот так, например:
CODE
struct TMyStruct
{
static const uint32 Const1 = 12;

//-- interger "constants" only
enum TSome
{
EItem1 = 0,
EItem2 = 13,
};

};


Компилятор, правда, нужен правильный sm.gif

и как оно будет выглядеть в памяти? Исходя из того что элементы структуры в памяти должна быть расположены линейно. А static const это другой тип памяти, если не ошибаюсь.
Keil - "правильный" компилятор?
CrimsonPig
Цитата(Atlantis- @ Dec 10 2015, 13:09) *
и как оно будет выглядеть в памяти? Исходя из того что элементы структуры в памяти должна быть расположены линейно. А static const это другой тип памяти, если не ошибаюсь.
Keil - "правильный" компилятор?


Если целочисленные константы заданы через enum, то они никак не будут выглядеть в памяти.
static const член структуры тоже, скорее всего ничего в памяти занимать не будет, компилятор его сократит просто до целочисленной константы, если, конечно, не страдать фигней и не пытаться брать адрес такой константы..
sigmaN
Вообще-то в С++ есть четко прописанные требования к standard layout классам(структурам). Тогда будет точно известно как оно лежит в памяти.
А еще есть требования к POD структурам, это те которые совсем простые и известно как в памяти и разрешено копировать через memcpy.
Такие вещи надо учитывать. Сейчас на вскидку не скажу, что там по поводу static members(кажется они идут мимо кассы и в sizeof(структура) не учитываются. Т.е. в памяти структуры не занимают ничего), но само объявление enum точно ничего не занимает. Занимать будет поле структуры с типом TSome. И размер будет == sizeof(int). В C++11 можно задать underlaying type и тогда может быть и не как int а как char например. Оч удобно для embedded однако.
Для просмотра полной версии этой страницы, пожалуйста, пройдите по ссылке.
Invision Power Board © 2001-2025 Invision Power Services, Inc.