Вопросы по С/С++ (СИ)

Если ваш вопрос не влез ни в одну из вышеперечисленных тем, вам сюда.
Ответить
Мудрый кот
Сообщения: 1854
Зарегистрирован: Вт авг 15, 2017 10:51:13

Сообщение jcxz »

[uquote="ROMan2947",url="/forum/viewtopic.php?p=3667834#p3667834"]Здравствуйте Уважаемые!
Столкнулся с такой ситуацией, что стало мне нужно в массив закинуть адреса полей структуры.Но что-то ничего не выходит, да и в сети не нашел ответа...Есть ли такая возможность в си?[/uquote]

В таких случаях лучше использовать указатели на члены структуры, а не просто указатели на uint8_t. Так:

Код: Выделить всё

struct Mytyp {
 u8 a, b, c;
};
static u8 Mytyp:: * const ttz[] = {&Mytyp::a, &Mytyp::b, &Mytyp::c};
Использование:

Код: Выделить всё

uint Func(Mytyp const *p)
{
  static u8 cnt = sizeof(ttz) / sizeof(ttz[0]);
  int i;
  if ((i = cnt - 1) < 0) i = sizeof(ttz) / sizeof(ttz[0]) - 1;
  cnt = i;
  return p->*ttz[i];
}
Разница думаю понятна. Хотя конкретно в Вашем случае (когда адресуемые члены расположены подряд), я бы использовал наложенный через union массив (как тут уже посоветовали).
Правда указатели на члены имеют размерность равную указателям и в случаях маленьких структур экономнее (по флеши) может быть просто хранить смещения к членам структуры и когда нужно - приводить тип.

PS: И ещё - в таких случаях как у вас (массив констант), нужно всё-таки использовать квалификатор const для массива указателей. Чтоб не тратить понапрасну ОЗУ.
Реклама
Грызет канифоль
Аватара пользователя
Сообщения: 287
Зарегистрирован: Сб янв 23, 2016 00:59:59
Откуда: Чебоксары

Сообщение ROMan2947 »

[uquote="jcxz",url="/forum/viewtopic.php?p=3668040#p3668040"]

Код: Выделить всё

static u8 Mytyp:: * const ttz[] = {&Mytyp::a, &Mytyp::b, &Mytyp::c};
[/uquote] чет не знаком мне этот :: синтаксис это не С++?

Добавлено after 28 minutes 49 seconds:
[uquote="WiseLord",url="/forum/viewtopic.php?p=3667981#p3667981"]Тогда можно проще, через union:
Спойлер

Код: Выделить всё

typedef union {
    struct {
        uint8_t sec;
        uint8_t min;
        uint8_t hour;
    };
    uint8_t time[3];
} Rtc;

/*
Расположение в памяти::
|             rtc             |
| sec     | min     | hour    |
| time[0] | time[1] | time[3] |
*/

[/uquote]

как это работает? :dont_know: почему в массив сразу залетают элементы структуры?
Реклама
Друг Кота
Аватара пользователя
Сообщения: 4906
Зарегистрирован: Чт апр 11, 2013 11:19:59
Откуда: Минск

Сообщение WiseLord »

Потому что это union. Один из базовых типов в C, кстати.
Контактная информация:
Грызет канифоль
Аватара пользователя
Сообщения: 287
Зарегистрирован: Сб янв 23, 2016 00:59:59
Откуда: Чебоксары

Сообщение ROMan2947 »

[uquote="WiseLord",url="/forum/viewtopic.php?p=3668478#p3668478"]Потому что это union. Один из базовых типов в C, кстати.[/uquote] в книге было дело про этот тип,но там как-то поверхностно описано было,и больше всего меня смутило как элементы,причем разных типов, занимают одну область памяти...а сейчас увидел то, что данные в структуре,что в массиве одинаковые......пока не понимаю для чего эти объединения нужны. пример бы конкретный увидеть.
Реклама
Эиком - электронные компоненты и радиодетали
Друг Кота
Аватара пользователя
Сообщения: 4906
Зарегистрирован: Чт апр 11, 2013 11:19:59
Откуда: Минск

Сообщение WiseLord »

А чем этот пример не устраивает?

В двух словах - все элементы union лежат в одной области памяти. Размер всего union-а равен максимальному из размеров его полей. Запись в любое из полей, соответственно, "портит" все остальные поля, потому что это одна и та же память.

Ещё один полезный пример:
Спойлер

Код: Выделить всё

typedef union {
    uint16_t word;
    struct {
        uint8_t byteL;
        uint8_t byteH;
    }
} WordType;

void function()
{
    WordType wt = 0x4567;

    // Теперь wt.byteL автоматически равно 0x67, а wt.byteH = 0x45
}
Контактная информация:
Реклама
Грызет канифоль
Аватара пользователя
Сообщения: 287
Зарегистрирован: Сб янв 23, 2016 00:59:59
Откуда: Чебоксары

Сообщение ROMan2947 »

[uquote="WiseLord",url="/forum/viewtopic.php?p=3668534#p3668534"]Ещё один полезный пример:[/uquote]
класс, теперь понял как это, и для чего можно применять! спасибо! только ещё момент, а что если в объединение определить тип int и float, что за каша получится?
Реклама
Мудрый кот
Сообщения: 1854
Зарегистрирован: Вт авг 15, 2017 10:51:13

Сообщение jcxz »

[uquote="ROMan2947",url="/forum/viewtopic.php?p=3668387#p3668387"][uquote="jcxz",url="/forum/viewtopic.php?p=3668040#p3668040"]

Код: Выделить всё

static u8 Mytyp:: * const ttz[] = {&Mytyp::a, &Mytyp::b, &Mytyp::c};
[/uquote] чет не знаком мне этот :: синтаксис это не С++?[/uquote]
С++. Прочитайте про "Указатели на член структуры/класса".
Это указатели на член типа структуры, а не на член конкретного экземпляра структуры (как у Вас). Т.е. - не указатель на ячейку памяти, а смещение члена структуры внутри структуры от её начала - если так понятнее. Их можно использовать с любым экземпляром структуры/класса.

Добавлено after 7 minutes 30 seconds:
[uquote="ROMan2947",url="/forum/viewtopic.php?p=3668599#p3668599"]класс, теперь понял как это, и для чего можно применять! спасибо! только ещё момент, а что если в объединение определить тип int и float, что за каша получится?[/uquote]
...то прочитав int получите бинарное содержимое float естественно.
union позволяет обращаться к одним и тем же данным разным способом. Например:
union {
u8 a[4];
u16 b[2];
u32 c;
};
позволяет обратиться к содержимому 32-битного значения c через a - побайтно, или через b - пословно (по 16-битно).
Ещё union можно использовать для принудительного выравнивания без прагм - если нужно чтобы структура struct A { u8 a, b, c;} содержащая только байтовые члены была выровнена на границу 4-х байт (на 32-битных системах), то можно сделать:
union {
struct A;
u32 align;
};
и прагмы не нужны, а значит будет корректно компилироваться разными компиляторами.
Грызет канифоль
Аватара пользователя
Сообщения: 287
Зарегистрирован: Сб янв 23, 2016 00:59:59
Откуда: Чебоксары

Сообщение ROMan2947 »

Доброго вечера!Не могу сообразить как проще и правильнее решить следующую задачу:
есть переменная типа UL. в ней хранится число,которое является показанием счетчика воды. максимальное число которое мне нужно это от 0 до 99999999 л. мне необходимо редактировать это число поразрядно,для задания данных ручками. мысль пока одна, считать область побайтно,после отработать с полубайтами и собрать снова все в кучу.Как-то мудрено получается.Хотелось бы услышать Ваши варианты. :roll:
Модератор
Аватара пользователя
Сообщения: 4618
Зарегистрирован: Чт мар 18, 2010 23:09:57
Откуда: Планета Земля

Сообщение Аlex »

Преобразовать в массив символов перед редактированием, после редактирования - обратно в число.
Мудрый кот
Сообщения: 1854
Зарегистрирован: Вт авг 15, 2017 10:51:13

Сообщение jcxz »

[uquote="ROMan2947",url="/forum/viewtopic.php?p=3669095#p3669095"]есть переменная типа UL. в ней хранится число,которое является показанием счетчика воды. максимальное число которое мне нужно это от 0 до 99999999 л. мне необходимо редактировать это число поразрядно,для задания данных ручками. мысль пока одна, считать область побайтно,после отработать с полубайтами и собрать снова все в кучу.[/uquote]
Почему "полубайтами"? Число в BCD-формате что-ль?
Если не BCD, а обычное бинарное, то:
Чтобы удалить цифру в дес.разряде ix из числа u32 x (со сдвигом в пустое место из более старших разрядов):

Код: Выделить всё

static u32 const tPow10[] = {
  1ul,
  10ul,
  100ul,
  1000ul,
  10000ul,
  100000ul,
  1000000ul,
  10000000ul,
  100000000ul,
  1000000000ul};
#define ncell(m) (sizeof(m) / sizeof((m)[0]))
u32 Del(u32 x, uint ix)
{
  assert(ix < ncell(tPow10));
  u32 i = x % tPow10[ix];
  if (ix < ncell(tPow10) - 1) i += x / tPow10[ix + 1] * tPow10[ix];
  return i;
}
Примерно так.
Вставка цифры со сдвигом других разрядов - аналогично, в обратном порядке.
Грызет канифоль
Аватара пользователя
Сообщения: 287
Зарегистрирован: Сб янв 23, 2016 00:59:59
Откуда: Чебоксары

Сообщение ROMan2947 »

[uquote="jcxz",url="/forum/viewtopic.php?p=3669133#p3669133"]Почему "полубайтами"? Число в BCD-формате что-ль?[/uquote]

допустим в моей переменной хранится десятичное число 12345678 или 0x‭BC614E‬;
дело в том,что эта переменная находиться в eeprom. стандартными функциями могу читать и писать побайтно->по 8 бит. считав один байт я получу
78 или 0x4E. т.е. два разряда 7 и 8, которые я должен редактировать отдельно. а после все это надо еще собрать в единое число
Поставщик валерьянки для Кота
Сообщения: 2089
Зарегистрирован: Вс июн 19, 2016 09:32:03

Сообщение Reflector »

[uquote="ROMan2947",url="/forum/viewtopic.php?p=3669249#p3669249"]допустим в моей переменной хранится десятичное число 12345678 или 0x‭BC614E‬;
дело в том,что эта переменная находиться в eeprom. стандартными функциями могу читать и писать побайтно->по 8 бит. считав один байт я получу 78 или 0x4E. т.е. два разряда 7 и 8, которые я должен редактировать отдельно.[/uquote]
А если число будет 87654321, то прочитав младший байт получишь 177, и что с ним потом делать? :)
Грызет канифоль
Аватара пользователя
Сообщения: 287
Зарегистрирован: Сб янв 23, 2016 00:59:59
Откуда: Чебоксары

Сообщение ROMan2947 »

[uquote="Reflector",url="/forum/viewtopic.php?p=3669262#p3669262"]А если число будет 87654321, то прочитав младший байт получишь 177, и что с ним потом делать? :)[/uquote] :shock: :o :kill: короче я так понял,что это число лучше не бомбить на отдельные цифры.будем прибавлять и отнимать лучше десятки, сотни,тысячи....так думаю правильнее
Мудрый кот
Сообщения: 1854
Зарегистрирован: Вт авг 15, 2017 10:51:13

Сообщение jcxz »

[uquote="ROMan2947",url="/forum/viewtopic.php?p=3669249#p3669249"]считав один байт я получу
78 или 0x4E. т.е. два разряда 7 и 8, которые я должен редактировать отдельно. а после все это надо еще собрать в единое число[/uquote]
В бинарных числах нет никакой связи между десятичными цифрами и байтами. То что Вы пишете справедливо лишь для BCD-чисел. Если у Вас такие числа, то да - так можно.

Добавлено after 1 minute 1 second:
[uquote="ROMan2947",url="/forum/viewtopic.php?p=3669264#p3669264"]короче я так понял,что это число лучше не бомбить на отдельные цифры.будем прибавлять и отнимать лучше десятки, сотни,тысячи....так думаю правильнее[/uquote]
Почему? Я же приводил процедуру как это делается. Чем не устраивает?
Грызет канифоль
Аватара пользователя
Сообщения: 287
Зарегистрирован: Сб янв 23, 2016 00:59:59
Откуда: Чебоксары

Сообщение ROMan2947 »

[uquote="jcxz",url="/forum/viewtopic.php?p=3669276#p3669276"]Почему? Я же приводил процедуру как это делается. Чем не устраивает?[/uquote]все отлично,я сначала не понял как ее применять,начал мутить свое,но в итоге пришел к тому же, что Вы и привели. синтаксис интересный у Вашего кода,это в чем так пишется?
ARV
Ум, честь и совесть. И скромность.
Аватара пользователя
Сообщения: 18797
Зарегистрирован: Чт дек 28, 2006 08:19:56
Откуда: Новочеркасск

Сообщение ARV »

Человек оперирует символами. Поэтому, когда человек должен изменить число, надо делать так, как удобно человеку, и не парить моск. Тем более что на экране число уже в виде символов.
Лучший совет был уже дан: перевести в строку, отредактировать посимвольно, и перевести в число обратно.
если рассматривать человека снизу, покажется, что мозг у него глубоко в жопе
при взгляде на многих сверху ничего не меняется...

Мой уютный бложик... заходите!
Контактная информация:
Поставщик валерьянки для Кота
Сообщения: 2089
Зарегистрирован: Вс июн 19, 2016 09:32:03

Сообщение Reflector »

[uquote="ARV",url="/forum/viewtopic.php?p=3669436#p3669436"]Человек оперирует символами. Поэтому, когда человек должен изменить число, надо делать так, как удобно человеку, и не парить моск. Тем более что на экране число уже в виде символов.
Лучший совет был уже дан: перевести в строку, отредактировать посимвольно, и перевести в число обратно.[/uquote]
Год назад была похожая тема, я тогда предлагал подход как у jcxz, в итоге ТС послушал остальных, тебя в том числе, и накатал функцию с массивом, в несколько раз большую по размеру, на порядок более медленную и весьма сомнительно, что хотя бы более понятную. По крайней мере у меня было явное сравнение с 60'000, т.к. это максимальное значение, а в другом варианте оно было поразрядно размазано по коду.
Мудрый кот
Сообщения: 1854
Зарегистрирован: Вт авг 15, 2017 10:51:13

Сообщение jcxz »

[uquote="ROMan2947",url="/forum/viewtopic.php?p=3669319#p3669319"]синтаксис интересный у Вашего кода,это в чем так пишется?[/uquote]
В смысле? Это си. Под 32-битный компилятор.
Грызет канифоль
Аватара пользователя
Сообщения: 287
Зарегистрирован: Сб янв 23, 2016 00:59:59
Откуда: Чебоксары

Сообщение ROMan2947 »

Сделал по методу jcxz, работает, да и понятно очень. Тем более вспомнилось, как-то по книге решал подобную задачу. С символами я бы запутался думаю.

Добавлено after 2 minutes 40 seconds:
[uquote="jcxz",url="/forum/viewtopic.php?p=3669722#p3669722"]В смысле? Это си. Под 32-битный компилятор.[/uquote]
в смысле, что вставил код в студию, а там часть типов неизвестны.
Мудрый кот
Сообщения: 1854
Зарегистрирован: Вт авг 15, 2017 10:51:13

Сообщение jcxz »

[uquote="ARV",url="/forum/viewtopic.php?p=3669436#p3669436"]Человек оперирует символами. Поэтому, когда человек должен изменить число, надо делать так, как удобно человеку, и не парить моск. Тем более что на экране число уже в виде символов.[/uquote]
Ну да - автору нужно изменить всего одну цифру, и для этого нужно будет выделить память, разобрать всё число на символы (много команд деления или умножения), изменить символ, потом обратно - собрать число из символов. И это - проще??? :facepalm:
Весь этот огород из кучи лишних операций вместо того, чтобы сделать только нужные операции - несколько делений/умножений.

PS: Впрочем это дело ТСа - ему виднее как ему удобнее. Может сделать и так и так.

Добавлено after 2 minutes 48 seconds:
[uquote="ROMan2947",url="/forum/viewtopic.php?p=3669725#p3669725"]в смысле, что вставил код в студию, а там часть типов неизвестны.[/uquote]
Ну не люблю я эти длинные uint32_t и т.п. которых в программе будет куча. :) Поэтому определил свой набор:

Код: Выделить всё

typedef unsigned char uchar;
typedef unsigned short ushort;
typedef unsigned int uint;
typedef unsigned long ulong;
typedef unsigned long long ulonglong;
typedef signed long long longlong;
typedef signed char s8;
typedef signed short s16;
typedef signed long s32;
typedef signed long long s64;
typedef unsigned char u8;
typedef unsigned short u16;
typedef unsigned long u32;
typedef unsigned long long u64;
Думаю они интуитивно понятны. Макрос ncell(), который у меня тоже повсеместно используется - я привёл его содержимое. assert() - вещь стандартная. А вроде больше там ничего необычного нет.... :dont_know:
Ответить

Вернуться в «Разные вопросы по МК»