Вопросы по С/С++ (СИ)
- Реклама
Не всегда лишнее. Так, 1900 делится на 4, но это не високосный год.
Хотя учитывая (year+2000) автора, он явно не собирается работать с такими годами, так что да, в диапазоне 1901..2099 функция будет работать с одним только %4.
Хотя учитывая (year+2000) автора, он явно не собирается работать с такими годами, так что да, в диапазоне 1901..2099 функция будет работать с одним только %4.
Хочу в пятом кейле сделать такую конструкцию: есть регистр, который описан как uint32_t. Я хочу его прочитать в переменную, но я еще хочу работать с его битовыми полями и потому определил структуру. Но, естесственно, я не могу сделать прямое присваивание регистра к этой структуре. Поэтому я обычно делал union:В IARе этот фокус прокатывал, присваивание делал prev_time_word, а дальше работал с полями prev_time. А вот кейл заявляет, что nothing declared и к полям prev_time доступа у меня нет.
Как быть?
Код: Выделить всё
union {
struct time_reg prev_time;
uint32_t prev_time_word;
}Как быть?
в более-менее свежих версиях компиляторов должны поддерживаться анонимные структуры:
ну и вообще лично я бы рекомендовал определить сначала тип-структуру, а потом в union уже использовать поле данного типа:
если регистр отображается в адресное пространство ОЗУ, то можно "совместить" этот регистр с нужным типом-union, чтобы не считывать его в отдельную переменную, а сразу работать с его содержимым.
Код: Выделить всё
union{
struct{
int field1;
int field2;
};
long field3;
} my_var;Код: Выделить всё
typedef struct {
int field1;
int field2;
} my_type;
union{
my_type field1;
long field2;
} my_var;если рассматривать человека снизу, покажется, что мозг у него глубоко в жопе
при взгляде на многих сверху ничего не меняется...
Мой уютный бложик... заходите!
при взгляде на многих сверху ничего не меняется...
Мой уютный бложик... заходите!
- Сообщения: 139
- Зарегистрирован: Чт фев 11, 2016 18:35:37
Да, только лучше бы подсократить:levaclaus писал(а):пытаюсь высчитать високосный\обычный год ... Верно ли это все?
Код: Выделить всё
bool LeapYear(int year)
{
return ( year%4 == 0 && year%100 != 0 || year%400 == 0 );
};Да, вплоть до 4 октября 1582 года так и считали, но на следующий день - 15 октября 1582 года - стали считать по принципу, заложенному в код выше.Аlex писал(а):Для вычисления високосного года, вот этого :достаточно.Код: Выделить всё
((year+2000) % 4 == 0)
А потом придет "Проблема 2100 года".WiseLord писал(а):так что да, в диапазоне 1901..2099 функция будет работать с одним только %4.
- Из овощей я больше всего люблю пельмени... © Соседский Мальчик
- Реклама
Доброго времени суток.
Есть глупый вопрос по логике использования функций в программе на C. Допустим, в основном цикле программы МК у меня выполняются некотороые преобразования с несколькими переменными. Я хочу разгрести бардак, распихав преобразования по фукнциям. Т.е. вызов первой функции - обработка данных с АЦП, вызов второй - подготовка их к выводу на дисплей, вызов третьей - обработка нажатия кнопоки. Но после работы каждой фукнции, в основной программе должны измениться несколько перменных (т.е. return'ом не обойдешься). Можно через работу с адресами переменных выводить полученные в функциях значения в основную программу, но как-то это извращенно выглядит.
Может я чего опять недопонял и есть как-то менее изуверский способ вынести элементы программы в отдельные функциональные блоки, которые смогут передавать друг другу данные?
Есть глупый вопрос по логике использования функций в программе на C. Допустим, в основном цикле программы МК у меня выполняются некотороые преобразования с несколькими переменными. Я хочу разгрести бардак, распихав преобразования по фукнциям. Т.е. вызов первой функции - обработка данных с АЦП, вызов второй - подготовка их к выводу на дисплей, вызов третьей - обработка нажатия кнопоки. Но после работы каждой фукнции, в основной программе должны измениться несколько перменных (т.е. return'ом не обойдешься). Можно через работу с адресами переменных выводить полученные в функциях значения в основную программу, но как-то это извращенно выглядит.
Может я чего опять недопонял и есть как-то менее изуверский способ вынести элементы программы в отдельные функциональные блоки, которые смогут передавать друг другу данные?
We do what we must because we can (c) GLaDOS
Ну почему ? Передача указателя (адреса переменной) в функцию - один из способов обработки данных внутри функции. Ничего извращённого в этом нет.baron_P писал(а):Можно через работу с адресами переменных выводить полученные в функциях значения в основную программу, но как-то это извращенно выглядит.
- Сообщения: 882
- Зарегистрирован: Ср фев 22, 2012 01:25:21
Можно еще не размещать эти переменные в main цикле, а описать их перед функкциями, тогда они станут глобальными, и к ним можно будет обращаться с любого места в программе...
Хотя конечно лучше чтобы глобальных переменных было по минимуму... но с другой стороны, редкая программа обходится без глобальных переменных...
Хотя конечно лучше чтобы глобальных переменных было по минимуму... но с другой стороны, редкая программа обходится без глобальных переменных...
У меня в голове эта возня с адресами не укладывается нормально: приходится потом много-много раз ошибки вычесывать. Может, конечно, если часто такой метод применять, то привыкну, но пока сложно.Аlex писал(а):Ну почему ? Передача указателя (адреса переменной) в функцию - один из способов обработки данных внутри функции. Ничего извращённого в этом нет.baron_P писал(а):Можно через работу с адресами переменных выводить полученные в функциях значения в основную программу, но как-то это извращенно выглядит.
Глобальные переменные - тоже решение. Я о них в таком контексте не думал почему-то.
We do what we must because we can (c) GLaDOS
Всем привет! Нужна помощь в выборе книги по программированию.
Надоело быдлокодить. Мозг требует новой информации. Есть ли что-нибудь ориентированное на структуру программы с адекватными примерами, про взаимодействие процессов, может даже будет затронута тема RTOS? Прочел книгу ди-халта (не помню как называется), в процессе изучения материал из книги С. Макконнелл «Совершенный код». Книга чертовски полезная, но ориентированна больше на чистоту кода, улучшения чтабельности кода и минимизацию ошибок.
Перекачал кучу. Ничего не нашел, что интересно подходит под описание выше. Решил спросить бывалых.
Надоело быдлокодить. Мозг требует новой информации. Есть ли что-нибудь ориентированное на структуру программы с адекватными примерами, про взаимодействие процессов, может даже будет затронута тема RTOS? Прочел книгу ди-халта (не помню как называется), в процессе изучения материал из книги С. Макконнелл «Совершенный код». Книга чертовски полезная, но ориентированна больше на чистоту кода, улучшения чтабельности кода и минимизацию ошибок.
Перекачал кучу. Ничего не нашел, что интересно подходит под описание выше. Решил спросить бывалых.
Теория — это когда все известно, но ничего не работает. Практика — это когда все работает, но никто не знает почему. Мы же объединяем теорию и практику: ничего не работает… и никто не знает почему!
© Альберт Эйнштейн
© Альберт Эйнштейн
- Сообщения: 574
- Зарегистрирован: Вт ноя 02, 2010 17:46:37
Вот тут есть хорошая подборка книг.
http://forum.shelek.ru/index.php/topic,28557.0.html
http://forum.shelek.ru/index.php/topic,28557.0.html
Можно пример пожалуйста.ARV писал(а): если регистр отображается в адресное пространство ОЗУ, то можно "совместить" этот регистр с нужным типом-union, чтобы не считывать его в отдельную переменную, а сразу работать с его содержимым.
P.S. и есче вопрос: можно ли в одной структуре определять больше битовых полей чем разрядность системы?
«И всё-таки она вертится!»
конкретный пример я пока не могу привести, но теорию могу рассказать.
допустим, в ОЗУ по адресу 0x0100 находится некий регистр REG, младшие 4 бита которого соответствуют какому-то предделителю, а старшие 4 - это какие-то флаги.
определяем тип для обращения к этим битам:это тип-структура с битовыми полями
но иногда нам будет надо работать с этим регистром сразу, как с байтом, поэтому создаем еще один тип-объединение:
теперь остается только "отмапить" этот тип на нужный адрес в ОЗУ, и все:так мы объявляем указатель, сразу инициализированный нужным значением (адресом). если наш регистр содержит некоторые биты/флаги, которые могут менять свое значение по каким-то аппаратным событиям, надо обязательно указывать volatile для соответствующих полей наших ранее созданных структур. ну или для указателя целиком. если содержимое этого регистра зависит только от наших действий, volatile можно не указывать
теперь при необходимости мы можем записать в регистр число сразуили установить только предделительили работать с любым из флагов
в общем, как-то так... на сколько я в курсе, подобным образом вся периферия ARM описана в соответствующих хедерах, и вся работа с нею ведется подобным образом
свежие версии компиляторов поддерживают и безымяные структуры внутри union-ов, поэтому можно чуть-чуть упростить:в этом случае для обращения к битам не надо будет указывать BITS, т.е. будет так:
P.S. количество битовых полей в структуре может быть любым - компилятор выделит нужное количество целых байтов под структуру. но делать отдельное поле размером, например, 65 битов недопустимо, т.к. Си не имеет встроенных средств для работы с числами большими, чем long long. иначе говоря, каждое битовое поле может иметь размер в битах такой, чтобы уложиться внутри любого стандартного типа Си (кроме float).
допустим, в ОЗУ по адресу 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;теперь при необходимости мы можем записать в регистр число сразу
Код: Выделить всё
REG->BYTE = 0x00;Код: Выделить всё
REG->BITS.DIV = 5;Код: Выделить всё
char data = REG->BITS.FLAG2 ? 12 : 32;свежие версии компиляторов поддерживают и безымяные структуры внутри 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;Код: Выделить всё
REG->DIV = 12;
data = REG->FLAG2 ? 12 : 32;если рассматривать человека снизу, покажется, что мозг у него глубоко в жопе
при взгляде на многих сверху ничего не меняется...
Мой уютный бложик... заходите!
при взгляде на многих сверху ничего не меняется...
Мой уютный бложик... заходите!
Спасибо большое, по поводу регистров понятно.
Когда битовому полю присваиваеш число, то берутся младшие байты в количестве длины поля, остальные отбрасываются или присваиваются те биты смотря где находится битовое поле в структуре?
Когда битовому полю присваиваеш число, то берутся младшие байты в количестве длины поля, остальные отбрасываются или присваиваются те биты смотря где находится битовое поле в структуре?
«И всё-таки она вертится!»
я не понял, что вы спросили, потому отвечу, как получится 
когда вы задаете длину битового поля, то тем самым как бы ограничиваете длину числа в битах. не смотря на то, что битовое поле int var : 3; имеет тип int, на самом деле в нем будет всего 3 бита! честно говоря, я не в курсе, будет ли выделен один бит под знак числа или нет - как-то не доводилось сталкиваться... но смысл именно в том, что фактически число будет из 3 битов.
далее все происходит по сишным правилам: при переполнении чисел остается только то, что влезло, остальное теряется. то есть если в 3-битное поле вы попытаетесь записать число 8, то на самом деле там окажется 0 (0b00001000). положение битового поля "внутри структуры" ни на что не влияет, т.е. всегда будут браться младшие биты по нужному количеству и помещаться туда, куда следует. то есть компилятор путем сдвигов сформирует нужное число и поместит его в байт, маскируя остальные биты, чтобы не изменить их содержимое. это, безусловно, означает, что доступ к битовым полям почти неизбежно будет медленнее, чем к "обычным" полям структуры "полного размера".
когда вы задаете длину битового поля, то тем самым как бы ограничиваете длину числа в битах. не смотря на то, что битовое поле int var : 3; имеет тип int, на самом деле в нем будет всего 3 бита! честно говоря, я не в курсе, будет ли выделен один бит под знак числа или нет - как-то не доводилось сталкиваться... но смысл именно в том, что фактически число будет из 3 битов.
далее все происходит по сишным правилам: при переполнении чисел остается только то, что влезло, остальное теряется. то есть если в 3-битное поле вы попытаетесь записать число 8, то на самом деле там окажется 0 (0b00001000). положение битового поля "внутри структуры" ни на что не влияет, т.е. всегда будут браться младшие биты по нужному количеству и помещаться туда, куда следует. то есть компилятор путем сдвигов сформирует нужное число и поместит его в байт, маскируя остальные биты, чтобы не изменить их содержимое. это, безусловно, означает, что доступ к битовым полям почти неизбежно будет медленнее, чем к "обычным" полям структуры "полного размера".
если рассматривать человека снизу, покажется, что мозг у него глубоко в жопе
при взгляде на многих сверху ничего не меняется...
Мой уютный бложик... заходите!
при взгляде на многих сверху ничего не меняется...
Мой уютный бложик... заходите!
У Вас получилось, мне все понятно, Спасибо!!! Есче интересно знать, битовые поля применяются когда оперативной памяти мало или просто для удобства. На сколько это выгоднее конструкции типа var |= 1 << 4;ARV писал(а):я не понял, что вы спросили, потому отвечу, как получится
«И всё-таки она вертится!»
Ассемблерный код вряд ли будет отличаться. Это, скорее, удобство для программиста.
- Сообщения: 353
- Зарегистрирован: Вс янв 19, 2014 22:41:55
И для удобства тоже. Если автор, к примеру, не находит метод использования битовых масок и операций приемлемо понятным для своей аудитории.Apparatchik писал(а):Есче интересно знать, битовые поля применяются когда оперативной памяти мало или просто для удобства.
В МК про битовые поля как правило вспоминают когда место под данные уже исчерпалось - а для кода этого места ещё осталось "шибко прельстиво обильно" - и вот, после того, как программирующий организм до отчаяния наиграется в "игру 15" целыми байтами - к нему в тревожный рассветный полудрём приходит Архимед и, лукаво подхихикивая в бороду, заставляет вспомнить про битовые поля, тут-же пробудиться с воплем "Эврика!" и одним прыжком переместиться к компьютеру. После чего та самая "игра в 15" продолжается уже на качественно новом уровне - за счёт того, что код пухнет от косвенных битовых операций, скрывающихся за этой филигранной красотой кода. При сём довольно быстро приходит понимание, что и от перестановки порядка таких переменных тоже можно выигрывать байтики. Нынче правда проще взять камешек поширше, нежели устраивать многочасовые экзерсисы с компилятором, заталкивая свои идейки в бюджетные прокрустовы восьмибитники. Хотя, нужно признать, что и экзерсисы оные порой обогащают весьма душеполезным опытом. Иначе как бы мне в межушное пространство, к примеру, дошло, что индекс для буфера размером кратным степени двойки можно сделать битовым полем соответствующей ширины, после чего смело его инкрементировать, не пачкая руки делением по модулю. Потомки, конечно, от такого компактного решения станут весьма агрессивно-благодарны, но ведь шикарно-же!
Одновременным нажатием LIGHT и POWER, РП Sangean ATS-909X (ver 1.29) превращается в ATS-909XR! 
Если я объявил структуру с битовыми полями, как её правильно инициализировать? Как обычную структуру, присвоить битовому полю число и компилятор возмет младшие биты?
«И всё-таки она вертится!»
Каждое поле по-отдельности, тем значением, которое необходимо при инициализации. Это же очевидно, или нет ?Apparatchik писал(а):как её правильно инициализировать?
Про младшие биты - не понятно.


