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

Если ваш вопрос не влез ни в одну из вышеперечисленных тем, вам сюда.
Ответить
Модератор
Аватара пользователя
Сообщения: 4618
Зарегистрирован: Чт мар 18, 2010 23:09:57
Откуда: Планета Земля

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

В общем - да. Но деление на 100 и на 400 - лишнее.
Реклама
Друг Кота
Аватара пользователя
Сообщения: 4905
Зарегистрирован: Чт апр 11, 2013 11:19:59
Откуда: Минск

Сообщение WiseLord »

Не всегда лишнее. Так, 1900 делится на 4, но это не високосный год.
Хотя учитывая (year+2000) автора, он явно не собирается работать с такими годами, так что да, в диапазоне 1901..2099 функция будет работать с одним только %4.
Контактная информация:
Реклама
Друг Кота
Аватара пользователя
Сообщения: 7382
Зарегистрирован: Пт авг 28, 2009 21:34:30
Откуда: 845-й км.

Сообщение uldemir »

Хочу в пятом кейле сделать такую конструкцию: есть регистр, который описан как uint32_t. Я хочу его прочитать в переменную, но я еще хочу работать с его битовыми полями и потому определил структуру. Но, естесственно, я не могу сделать прямое присваивание регистра к этой структуре. Поэтому я обычно делал union:

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

union {
  struct time_reg prev_time;
  uint32_t prev_time_word;
}
В IARе этот фокус прокатывал, присваивание делал prev_time_word, а дальше работал с полями prev_time. А вот кейл заявляет, что nothing declared и к полям prev_time доступа у меня нет.

Как быть?
ARV
Ум, честь и совесть. И скромность.
Аватара пользователя
Сообщения: 18787
Зарегистрирован: Чт дек 28, 2006 08:19:56
Откуда: Новочеркасск

Сообщение ARV »

в более-менее свежих версиях компиляторов должны поддерживаться анонимные структуры:

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

union{
   struct{
       int field1;
       int field2;
   };
   long field3;
} my_var;
ну и вообще лично я бы рекомендовал определить сначала тип-структуру, а потом в union уже использовать поле данного типа:

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

typedef struct {
   int field1;
   int field2;
} my_type;

union{
   my_type field1;
   long field2;
} my_var;
если регистр отображается в адресное пространство ОЗУ, то можно "совместить" этот регистр с нужным типом-union, чтобы не считывать его в отдельную переменную, а сразу работать с его содержимым.
если рассматривать человека снизу, покажется, что мозг у него глубоко в жопе
при взгляде на многих сверху ничего не меняется...

Мой уютный бложик... заходите!
Контактная информация:
Реклама
Эиком - электронные компоненты и радиодетали
Встал на лапы
Сообщения: 139
Зарегистрирован: Чт фев 11, 2016 18:35:37

Сообщение L.O.D »

levaclaus писал(а):пытаюсь высчитать високосный\обычный год ... Верно ли это все?
Да, только лучше бы подсократить:

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

bool    LeapYear(int year)
{
   return ( year%4 == 0 && year%100 != 0 || year%400 == 0 );
};
"+2000" опущено, для ясности.
Аlex писал(а):Для вычисления високосного года, вот этого :

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

((year+2000) % 4 == 0)
достаточно.
Да, вплоть до 4 октября 1582 года так и считали, но на следующий день - 15 октября 1582 года - стали считать по принципу, заложенному в код выше.
WiseLord писал(а):так что да, в диапазоне 1901..2099 функция будет работать с одним только %4.
А потом придет "Проблема 2100 года". :)
- Из овощей я больше всего люблю пельмени... © Соседский Мальчик
Реклама
Нашел транзистор. Понюхал.
Аватара пользователя
Сообщения: 183
Зарегистрирован: Вт сен 14, 2010 23:07:10
Откуда: Ростов

Сообщение baron_P »

Доброго времени суток.
Есть глупый вопрос по логике использования функций в программе на C. Допустим, в основном цикле программы МК у меня выполняются некотороые преобразования с несколькими переменными. Я хочу разгрести бардак, распихав преобразования по фукнциям. Т.е. вызов первой функции - обработка данных с АЦП, вызов второй - подготовка их к выводу на дисплей, вызов третьей - обработка нажатия кнопоки. Но после работы каждой фукнции, в основной программе должны измениться несколько перменных (т.е. return'ом не обойдешься). Можно через работу с адресами переменных выводить полученные в функциях значения в основную программу, но как-то это извращенно выглядит.
Может я чего опять недопонял и есть как-то менее изуверский способ вынести элементы программы в отдельные функциональные блоки, которые смогут передавать друг другу данные?
We do what we must because we can (c) GLaDOS
Реклама
Модератор
Аватара пользователя
Сообщения: 4618
Зарегистрирован: Чт мар 18, 2010 23:09:57
Откуда: Планета Земля

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

baron_P писал(а):Можно через работу с адресами переменных выводить полученные в функциях значения в основную программу, но как-то это извращенно выглядит.
Ну почему ? Передача указателя (адреса переменной) в функцию - один из способов обработки данных внутри функции. Ничего извращённого в этом нет.
Опытный кот
Аватара пользователя
Сообщения: 882
Зарегистрирован: Ср фев 22, 2012 01:25:21

Сообщение shads »

Можно еще не размещать эти переменные в main цикле, а описать их перед функкциями, тогда они станут глобальными, и к ним можно будет обращаться с любого места в программе...
Хотя конечно лучше чтобы глобальных переменных было по минимуму... но с другой стороны, редкая программа обходится без глобальных переменных...
Нашел транзистор. Понюхал.
Аватара пользователя
Сообщения: 183
Зарегистрирован: Вт сен 14, 2010 23:07:10
Откуда: Ростов

Сообщение baron_P »

Аlex писал(а):
baron_P писал(а):Можно через работу с адресами переменных выводить полученные в функциях значения в основную программу, но как-то это извращенно выглядит.
Ну почему ? Передача указателя (адреса переменной) в функцию - один из способов обработки данных внутри функции. Ничего извращённого в этом нет.
У меня в голове эта возня с адресами не укладывается нормально: приходится потом много-много раз ошибки вычесывать. Может, конечно, если часто такой метод применять, то привыкну, но пока сложно.

Глобальные переменные - тоже решение. Я о них в таком контексте не думал почему-то.
We do what we must because we can (c) GLaDOS
Сверлит текстолит когтями
Аватара пользователя
Сообщения: 1132
Зарегистрирован: Пт фев 16, 2007 14:18:20
Откуда: Новосибирск

Сообщение Chip115 »

Всем привет! Нужна помощь в выборе книги по программированию.
Надоело быдлокодить. Мозг требует новой информации. Есть ли что-нибудь ориентированное на структуру программы с адекватными примерами, про взаимодействие процессов, может даже будет затронута тема RTOS? Прочел книгу ди-халта (не помню как называется), в процессе изучения материал из книги С. Макконнелл «Совершенный код». Книга чертовски полезная, но ориентированна больше на чистоту кода, улучшения чтабельности кода и минимизацию ошибок.
Перекачал кучу. Ничего не нашел, что интересно подходит под описание выше. Решил спросить бывалых.
Теория — это когда все известно, но ничего не работает. Практика — это когда все работает, но никто не знает почему. Мы же объединяем теорию и практику: ничего не работает… и никто не знает почему!
© Альберт Эйнштейн
Контактная информация:
Вымогатель припоя
Сообщения: 574
Зарегистрирован: Вт ноя 02, 2010 17:46:37

Сообщение pokk »

Вот тут есть хорошая подборка книг.
http://forum.shelek.ru/index.php/topic,28557.0.html
Держит паяльник хвостом
Аватара пользователя
Сообщения: 908
Зарегистрирован: Вс май 23, 2010 13:55:42
Откуда: Украина, Александрия

Сообщение Apparatchik »

ARV писал(а): если регистр отображается в адресное пространство ОЗУ, то можно "совместить" этот регистр с нужным типом-union, чтобы не считывать его в отдельную переменную, а сразу работать с его содержимым.
Можно пример пожалуйста.

P.S. и есче вопрос: можно ли в одной структуре определять больше битовых полей чем разрядность системы?
«И всё-таки она вертится!»
ARV
Ум, честь и совесть. И скромность.
Аватара пользователя
Сообщения: 18787
Зарегистрирован: Чт дек 28, 2006 08:19:56
Откуда: Новочеркасск

Сообщение ARV »

конкретный пример я пока не могу привести, но теорию могу рассказать.

допустим, в ОЗУ по адресу 0x0100 находится некий регистр REG, младшие 4 бита которого соответствуют какому-то предделителю, а старшие 4 - это какие-то флаги.

определяем тип для обращения к этим битам:

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

typedef struct{
   unsigned char DIV : 4; // младшие 4 бита - делитель
   unsigned char FLAG1 : 1;
   unsigned char FLAG2 : 1;
   unsigned char FLAG3 : 1;
   unsigned char FLAG4 : 1;
} reg_bits;
это тип-структура с битовыми полями

но иногда нам будет надо работать с этим регистром сразу, как с байтом, поэтому создаем еще один тип-объединение:

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

typedef union{
   reg_bits BITS; // это для доступа к битам
   unsigned char BYTE; // это для доступа сразу к байту
} reg_type;
теперь остается только "отмапить" этот тип на нужный адрес в ОЗУ, и все:

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

reg_type *REG = (void*)0x0100;
так мы объявляем указатель, сразу инициализированный нужным значением (адресом). если наш регистр содержит некоторые биты/флаги, которые могут менять свое значение по каким-то аппаратным событиям, надо обязательно указывать volatile для соответствующих полей наших ранее созданных структур. ну или для указателя целиком. если содержимое этого регистра зависит только от наших действий, volatile можно не указывать

теперь при необходимости мы можем записать в регистр число сразу

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

REG->BYTE = 0x00;
или установить только предделитель

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

REG->BITS.DIV = 5;
или работать с любым из флагов

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

char data = REG->BITS.FLAG2 ? 12 : 32;
в общем, как-то так... на сколько я в курсе, подобным образом вся периферия ARM описана в соответствующих хедерах, и вся работа с нею ведется подобным образом

свежие версии компиляторов поддерживают и безымяные структуры внутри union-ов, поэтому можно чуть-чуть упростить:

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

typedef union{
   unsigned char BYTE;
   struct{
      unsigned char DIV : 4; // младшие 4 бита - делитель
      unsigned char FLAG1 : 1;
      unsigned char FLAG2 : 1;
      unsigned char FLAG3 : 1;
      unsigned char FLAG4 : 1;
   };
} reg_type;
в этом случае для обращения к битам не надо будет указывать BITS, т.е. будет так:

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

REG->DIV = 12;
data = REG->FLAG2 ? 12 : 32;
P.S. количество битовых полей в структуре может быть любым - компилятор выделит нужное количество целых байтов под структуру. но делать отдельное поле размером, например, 65 битов недопустимо, т.к. Си не имеет встроенных средств для работы с числами большими, чем long long. иначе говоря, каждое битовое поле может иметь размер в битах такой, чтобы уложиться внутри любого стандартного типа Си (кроме float).
если рассматривать человека снизу, покажется, что мозг у него глубоко в жопе
при взгляде на многих сверху ничего не меняется...

Мой уютный бложик... заходите!
Контактная информация:
Держит паяльник хвостом
Аватара пользователя
Сообщения: 908
Зарегистрирован: Вс май 23, 2010 13:55:42
Откуда: Украина, Александрия

Сообщение Apparatchik »

Спасибо большое, по поводу регистров понятно.

Когда битовому полю присваиваеш число, то берутся младшие байты в количестве длины поля, остальные отбрасываются или присваиваются те биты смотря где находится битовое поле в структуре?
«И всё-таки она вертится!»
ARV
Ум, честь и совесть. И скромность.
Аватара пользователя
Сообщения: 18787
Зарегистрирован: Чт дек 28, 2006 08:19:56
Откуда: Новочеркасск

Сообщение ARV »

я не понял, что вы спросили, потому отвечу, как получится :)))

когда вы задаете длину битового поля, то тем самым как бы ограничиваете длину числа в битах. не смотря на то, что битовое поле int var : 3; имеет тип int, на самом деле в нем будет всего 3 бита! честно говоря, я не в курсе, будет ли выделен один бит под знак числа или нет - как-то не доводилось сталкиваться... но смысл именно в том, что фактически число будет из 3 битов.

далее все происходит по сишным правилам: при переполнении чисел остается только то, что влезло, остальное теряется. то есть если в 3-битное поле вы попытаетесь записать число 8, то на самом деле там окажется 0 (0b00001000). положение битового поля "внутри структуры" ни на что не влияет, т.е. всегда будут браться младшие биты по нужному количеству и помещаться туда, куда следует. то есть компилятор путем сдвигов сформирует нужное число и поместит его в байт, маскируя остальные биты, чтобы не изменить их содержимое. это, безусловно, означает, что доступ к битовым полям почти неизбежно будет медленнее, чем к "обычным" полям структуры "полного размера".
если рассматривать человека снизу, покажется, что мозг у него глубоко в жопе
при взгляде на многих сверху ничего не меняется...

Мой уютный бложик... заходите!
Контактная информация:
Держит паяльник хвостом
Аватара пользователя
Сообщения: 908
Зарегистрирован: Вс май 23, 2010 13:55:42
Откуда: Украина, Александрия

Сообщение Apparatchik »

ARV писал(а):я не понял, что вы спросили, потому отвечу, как получится :)))
У Вас получилось, мне все понятно, Спасибо!!! Есче интересно знать, битовые поля применяются когда оперативной памяти мало или просто для удобства. На сколько это выгоднее конструкции типа var |= 1 << 4;
«И всё-таки она вертится!»
Друг Кота
Аватара пользователя
Сообщения: 4905
Зарегистрирован: Чт апр 11, 2013 11:19:59
Откуда: Минск

Сообщение WiseLord »

Ассемблерный код вряд ли будет отличаться. Это, скорее, удобство для программиста.
Контактная информация:
Потрогал лапой паяльник
Аватара пользователя
Сообщения: 353
Зарегистрирован: Вс янв 19, 2014 22:41:55

Сообщение Siarzhuk »

Apparatchik писал(а):Есче интересно знать, битовые поля применяются когда оперативной памяти мало или просто для удобства.
И для удобства тоже. Если автор, к примеру, не находит метод использования битовых масок и операций приемлемо понятным для своей аудитории.
В МК про битовые поля как правило вспоминают когда место под данные уже исчерпалось - а для кода этого места ещё осталось "шибко прельстиво обильно" - и вот, после того, как программирующий организм до отчаяния наиграется в "игру 15" целыми байтами - к нему в тревожный рассветный полудрём приходит Архимед и, лукаво подхихикивая в бороду, заставляет вспомнить про битовые поля, тут-же пробудиться с воплем "Эврика!" и одним прыжком переместиться к компьютеру. После чего та самая "игра в 15" продолжается уже на качественно новом уровне - за счёт того, что код пухнет от косвенных битовых операций, скрывающихся за этой филигранной красотой кода. При сём довольно быстро приходит понимание, что и от перестановки порядка таких переменных тоже можно выигрывать байтики. Нынче правда проще взять камешек поширше, нежели устраивать многочасовые экзерсисы с компилятором, заталкивая свои идейки в бюджетные прокрустовы восьмибитники. Хотя, нужно признать, что и экзерсисы оные порой обогащают весьма душеполезным опытом. Иначе как бы мне в межушное пространство, к примеру, дошло, что индекс для буфера размером кратным степени двойки можно сделать битовым полем соответствующей ширины, после чего смело его инкрементировать, не пачкая руки делением по модулю. Потомки, конечно, от такого компактного решения станут весьма агрессивно-благодарны, но ведь шикарно-же! ;)
Одновременным нажатием LIGHT и POWER, РП Sangean ATS-909X (ver 1.29) превращается в ATS-909XR! ;-)
Держит паяльник хвостом
Аватара пользователя
Сообщения: 908
Зарегистрирован: Вс май 23, 2010 13:55:42
Откуда: Украина, Александрия

Сообщение Apparatchik »

Если я объявил структуру с битовыми полями, как её правильно инициализировать? Как обычную структуру, присвоить битовому полю число и компилятор возмет младшие биты?
«И всё-таки она вертится!»
Модератор
Аватара пользователя
Сообщения: 4618
Зарегистрирован: Чт мар 18, 2010 23:09:57
Откуда: Планета Земля

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

Apparatchik писал(а):как её правильно инициализировать?
Каждое поле по-отдельности, тем значением, которое необходимо при инициализации. Это же очевидно, или нет ? :dont_know:
Про младшие биты - не понятно.
Ответить

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