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

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

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

Сообщение ARV »

ну сами поглядите:
1. calibrate у вас равно 0xF420
2. так как операции больше и меньше имеют одинаковый приоритет, выполняются они слева направо, т.е. как бы вот так ((0xF618<calibrate)<OxF230)
3. 0xF618<calibrate ----> 0xF618 < 0xF420. это выражение ЛОЖНО, т.е. имеет результат 0
4. теперь этот результат сравнивается с другим пределом: 0 < 0xF230 - это выражение всегда истинно, т.е. есть условие для срабатывания if
5. if срабатывает и перезаписывает вашу переменную...
если рассматривать человека снизу, покажется, что мозг у него глубоко в жопе
при взгляде на многих сверху ничего не меняется...

Мой уютный бложик... заходите!
Реклама
Аватара пользователя
levaclaus
Потрогал лапой паяльник
Сообщения: 302
Зарегистрирован: Пн янв 07, 2008 16:56:28
Откуда: Минск

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

Сообщение levaclaus »

ARV писал(а):ну сами поглядите:
1. calibrate у вас равно 0xF420
2. так как операции больше и меньше имеют одинаковый приоритет, выполняются они слева направо, т.е. как бы вот так ((0xF618<calibrate)<OxF230)
3. 0xF618<calibrate ----> 0xF618 < 0xF420. это выражение ЛОЖНО, т.е. имеет результат 0
4. теперь этот результат сравнивается с другим пределом: 0 < 0xF230 - это выражение всегда истинно, т.е. есть условие для срабатывания if
5. if срабатывает и перезаписывает вашу переменную...
просто
Когда-то давно и не правда я писал так, девайс работает и сейчас.

if (1500<calibrate_eeprom<500) {
calibrate_eeprom=1000;
};


calibrate=calibrate_eeprom;
Реклама
Аватара пользователя
ARV
Ум, честь и совесть. И скромность.
Сообщения: 18647
Зарегистрирован: Чт дек 28, 2006 08:19:56
Откуда: Новочеркасск
Контактная информация:

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

Сообщение ARV »

тогда в чем вопрос? если работает, значит, вы все правильно делаете. а если не работает - не правильно.
только если делаете правильно, то работает всегда, а когда не правильно - иной раз, как фишка ляжет. чувствуете разницу? ;)
если рассматривать человека снизу, покажется, что мозг у него глубоко в жопе
при взгляде на многих сверху ничего не меняется...

Мой уютный бложик... заходите!
Аватара пользователя
acckyiboxxx
Нашел транзистор. Понюхал.
Сообщения: 182
Зарегистрирован: Ср янв 25, 2012 07:26:40

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

Сообщение acckyiboxxx »

Здравствуйте где-бы мне почитать про следующие способы записи кода :

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

PORTB |= (0<<PB5)|(0<<PB6)|(0<<PB7);
пользоваться такой записью умею тупо зазубрив ее но хотелось-бы еще понимать , а на данный момент такая запись вызывает в моем мозгу следующий бред "порт б или равно лапа5=0 или равно лапа6=0 или равно лапа7=0 " хотя на самом деле это просто установка нужных бит порта, в данном случае в нули

и второй вопрос , почему когда я использую преобразование типов переменных размер скомпиленного файла увеличиваеться просто баснословно не стану приводить весь код но когда регистру присваиваю значение следующим образом :

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

OCR3C = 0xff;

то размер скомпиленного бинаря 350 байт

но когда пытаюсь работать с процентами и переволить тип float в char слкдующим образом

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

OCR3C = (char) (hot * 2.55);
то получаю аж 3130 байт при этом ничего кроме этой строчки в коде не меняю (перменная hot имеет тип float)

для своих проектов юзаю avr-gcc
Реклама
Эиком - электронные компоненты и радиодетали
Аватара пользователя
Леонид Иванович
Друг Кота
Сообщения: 4779
Зарегистрирован: Сб апр 02, 2011 12:40:46
Откуда: Минск
Контактная информация:

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

Сообщение Леонид Иванович »

acckyiboxxx писал(а):хотя на самом деле это просто установка нужных бит порта, в данном случае в нули
Запись абсолютно бессмысленная, поэтому Вы ее не понимаете. Приведенная строчка не делает ровным счетом ничего - логическое "или" с нулем не меняет значения.
acckyiboxxx писал(а):то получаю аж 3130 байт при этом ничего кроме этой строчки в коде не меняю (перменная hot имеет тип float
А чему тут удивляться? Подключаются библиотечные функции работы с плавающей точкой.
Реклама
Аватара пользователя
WiseLord
Друг Кота
Сообщения: 4905
Зарегистрирован: Чт апр 11, 2013 11:19:59
Откуда: Минск
Контактная информация:

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

Сообщение WiseLord »

Стоит добавить, что AVR - это всё-таки восьмибитный целочисленный контроллер. Операции с другими числами - 16-битнными и 32-битными целыми и, особенно, дробными - разворачиваются компилятором в довольно сложные и выполняющиеся гораздо дольше конструкции над теми же целыми 8-битными. Так что размер кода вырастает катастрофически.
Кстати, подобное наблюдается и при использовании многих функций из той же stdlib (разные printf-ы и прочие).
Реклама
Аватара пользователя
acckyiboxxx
Нашел транзистор. Понюхал.
Сообщения: 182
Зарегистрирован: Ср янв 25, 2012 07:26:40

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

Сообщение acckyiboxxx »

Леонид Иванович, не могли-бы вы ткнуть меня носом в хороший мануал по работе с такими конструкциями , а еще лучше в учебник в котором все изложено доступным языком
Аватара пользователя
ARV
Ум, честь и совесть. И скромность.
Сообщения: 18647
Зарегистрирован: Чт дек 28, 2006 08:19:56
Откуда: Новочеркасск
Контактная информация:

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

Сообщение ARV »

а можно я ткну? ;)
вообще-то, книг по языку Си - воз и маленькая тележка, если в гугле не забанили, то найти проще, чем нос утереть...
однако, если книжки искать и читать лень, могу предложить небольшие краткие советы лично от себя: http://arv.radioliga.com/content/category/6/33/49/
если рассматривать человека снизу, покажется, что мозг у него глубоко в жопе
при взгляде на многих сверху ничего не меняется...

Мой уютный бложик... заходите!
Аватара пользователя
baghear
Опытный кот
Сообщения: 791
Зарегистрирован: Вт июн 17, 2014 00:34:26

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

Сообщение baghear »

Добрый день подскажите пожалуйста, что означает данные предупреждения
Warning pointer targets in passing argument 1 of 'strlen_P' differ in signedness [-Wpointer-sign]
Warning passing argument 6 of 'show_string' from incompatible pointer type [enabled by default]
Аватара пользователя
Siarzhuk
Потрогал лапой паяльник
Сообщения: 353
Зарегистрирован: Вс янв 19, 2014 22:41:55

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

Сообщение Siarzhuk »

baghear писал(а):Warning pointer targets in passing argument 1 of 'strlen_P' differ in signedness [-Wpointer-sign]
char может быть знаковым и беззнаковым - смотрите что от вас ожидают, и что вы на самом деле передаёте в strlen. И какой тип char у используемого компилятора задан по умолчанию.
baghear писал(а):Warning passing argument 6 of 'show_string' from incompatible pointer type [enabled by default]
Опять-же ожидаемый тип указателя в шестом параметре функции show_string не соответствует тому, что в него передаёте. Код покажете - можно будет сказать точнее.
Одновременным нажатием LIGHT и POWER, РП Sangean ATS-909X (ver 1.29) превращается в ATS-909XR! ;-)
Аватара пользователя
baghear
Опытный кот
Сообщения: 791
Зарегистрирован: Вт июн 17, 2014 00:34:26

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

Сообщение baghear »

Есть такая функция
void show_string (unsigned char size,unsigned int start_x,unsigned int start_y,unsigned int color,unsigned int phone,const unsigned char *string)
последним параметром надо передать указатель
const unsigned char string_1 [] PROGMEM = "hello";
передаю вот так
show_string(3,4,2,0XAAAA,0XEEEE, &string_1);
а ошибки не выдает когда передаю так
show_string(3,4,2,0XAAAA,0XEEEE, string_1);
Прочитал что при передаче массива по сути передаю указатель на первый элемент.
Спасибо.
Аватара пользователя
Siarzhuk
Потрогал лапой паяльник
Сообщения: 353
Зарегистрирован: Вс янв 19, 2014 22:41:55

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

Сообщение Siarzhuk »

baghear писал(а):Есть такая функция
void show_string (unsigned char size,unsigned int start_x,unsigned int start_y,unsigned int color,unsigned int phone,const unsigned char *string)
последним параметром надо передать указатель
const unsigned char string_1 [] PROGMEM = "hello";
передаю вот так
show_string(3,4,2,0XAAAA,0XEEEE, &string_1);
Такой подход с легкой правкой имеет право на жизнь, можно использовать если требуется передавать строке начиная не с первого символа:

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

show_string(3,4,2,0XAAAA,0XEEEE, &string_1[3]);
Можно возразить, что написав

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

show_string(3,4,2,0XAAAA,0XEEEE, string_1 + 3);
мы достигнем того-же результата и покажемся себе в зеркале более продвинутыми, но по моему мнению, некоторая неуклюжесть первого варианта заставит потомков зацепится взглядом и таки заметить что там "не с нуля". Хотя комментарий, конечно, надёжнее...
baghear писал(а): а ошибки не выдает когда передаю так
show_string(3,4,2,0XAAAA,0XEEEE, string_1);
Прочитал что при передаче массива по сути передаю указатель на первый элемент.
да,а прибавление к указателю целого числа N - суть смещение в массиве на N-ое количество элементов.

А если написать для эксперимента так:

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

show_string(3,4,2,0XAAAA,0XEEEE, "hello");
то с некоторой долей вероятности можно получить от компилятора предупреждение о несоответствии типа указателя - поскольку строковый литерал дефолтного типа signed char* а в прототипе функции указан что нужен unsigned char*. Шибко переразвитые компиляторы зело полюбляют нас на этом подлавливать. ;-)

Удачи!
Одновременным нажатием LIGHT и POWER, РП Sangean ATS-909X (ver 1.29) превращается в ATS-909XR! ;-)
Аватара пользователя
baghear
Опытный кот
Сообщения: 791
Зарегистрирован: Вт июн 17, 2014 00:34:26

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

Сообщение baghear »

Спасибо большое, стало понятнее!!!!
Почему строковый литерал по дефолту signed char?
разве есть смысл учитывать знак при кодировке?

Еще возник вопрос, есть хэдер, который содержит один массив
static unsigned char const Font8x16[95][16] = {.....}
для чего он объявлен как static?
Аватара пользователя
Siarzhuk
Потрогал лапой паяльник
Сообщения: 353
Зарегистрирован: Вс янв 19, 2014 22:41:55

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

Сообщение Siarzhuk »

baghear писал(а):Спасибо большое, стало понятнее!!!!
Почему строковый литерал по дефолту signed char?
разве есть смысл учитывать знак при кодировке?
Точно не скажу, но навскидку это настройка компилятора - будет дефолтный char со знаком или без. А вот зачем - этим я как-то не задумывался. Что-то в памяти рядом с триграфами и прочей жуткой легаси болтается - но утверждать не возьмусь.
baghear писал(а):Еще возник вопрос, есть хэдер, который содержит один массив
static unsigned char const Font8x16[95][16] = {.....}
для чего он объявлен как static?
При включении хидеров в сишник - препроцессор формирует один большой файл который и скармливается компилятору. Т.е. выделив массив прямо в хидере - автор выделил его во всех сишниках в которые он будет включен. Компилятор эти массивы так и вставит в результирующие объектные файлы - ведь он работает с одним сишником за проход. После компилятора, как д'Артаньян на белом коне подъезжает линкер и начинает вязать объектники в единое целое. И тут он находит в различных файлах объекты с одинаковыми именами Font8x16 - и резонно начинает нудить про дубликаты символов и отказываться от своей миссии - ему и на самом деле непонятно какие ссылки идут к "тому" экземпляру, а какие к "этому". Но автор, умная голова, объявляет массив в хидере как static и теперь линкер вяжет ссылки из "этого" файла к его собственной копии массива, а из "того" файла - к "той" копии. Вуаля! Автор удовлетворён, счастливы все кроме процессора, ресурсы которого потрачены на несколько копий одних и тех-же данных. Вот где-то так, по моим ощущениям всё и происходило.

Чтобы избежать дубликации - нужно либо не включать хидер в несколько c-файлов, а если нужны ссылки между модулями - в хидере объявить его как extern вместо static, а тельце с инициализацией поместить в одном из c-шников.
Одновременным нажатием LIGHT и POWER, РП Sangean ATS-909X (ver 1.29) превращается в ATS-909XR! ;-)
Аватара пользователя
baghear
Опытный кот
Сообщения: 791
Зарегистрирован: Вт июн 17, 2014 00:34:26

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

Сообщение baghear »

Спасибо, большое!!!!
Аватара пользователя
acckyiboxxx
Нашел транзистор. Понюхал.
Сообщения: 182
Зарегистрирован: Ср янв 25, 2012 07:26:40

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

Сообщение acckyiboxxx »

непонятно почему единоразово самопроизвольно срабатывает прерывание int7 (судя по симуляции в протеусе)

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

ISR(INT7_vect){
	disable_int7();
	PORTB = ~PORTB; // для того что-бы глянуть что прерывание отработало
}

void init_encoders(void){
	//disable_int7(); // РУБИМ ПРЕРЫВАНИЕ ПО INT7
	cli(); // ВЫРУБАЕМ ПРЕРЫВАНИЯ ГЛОБАЛЬНО
	DDRE &=  (1<<DDE7); 
	PORTE &=  (1<<PE7); 
	EICRB |= (1<<ISC71) | (1<<ISC70) | (1<<ISC61) | (1<<ISC60); // INT6 И INT7 СРАБОТАЮТ ПО 2-М ВЫБОРКАМ ВЫСОКОГО УРОВНЯ
	sei(); // ГЛОБАЛЬНО РАЗРЕШАЕМ ПРЕРЫВАНИЯ
}

void enable_int7(void){
	cli(); // ВЫРУБАЕМ ПРЕРЫВАНИЯ ГЛОБАЛЬНО
	EIMSK = (1<<INT7); // РАЗРЕШАЕМ ПРЕРЫВАНИЕ НА INT7
	sei(); // ГЛОБАЛЬНО РАЗРЕШАЕМ ПРЕРЫВАНИЯ
}

void disable_int7(void){
	cli(); // ВЫРУБАЕМ ПРЕРЫВАНИЯ ГЛОБАЛЬНО
	EIMSK &= (1<<INT7); // ЗАПРЕЩАЕМ ПРЕРЫВАНИЕ НА INT7
	sei(); // ГЛОБАЛЬНО РАЗРЕШАЕМ ПРЕРЫВАНИЯ
	PORTB = 0x00;
}

int main(){
	init_encoders(); // НАСТРАИВАЕМ РАБОТУ ЭНКОДЕРОВ
	disable_int7();
	enable_int7();
	while (1)
	{
	};
	return 0;
}
так вот PE7 подтянут резюком к земле а энкодер может подавать на него лог единицу , после чего прерывания должны отключиться и PORTB должен выдать лог единицу на все свои 8 лап , только вот при симуляции в протеусе прерывание уже прилетает еще до того как я начинаю "крутить энкодер"

энкодер запилен по этой статье http://diymicro.ru/sozdanie-ierarxiches ... odera.html вирт. осциллографом проверял от него самопроизвольно лог единица прилетать не может

да и настройки тоже вроде как правильно сделал http://www.gaw.ru/html.cgi/txt/doc/micr ... h128/8.htm

вопрос в том почему прерывание все-же срабатывает первый раз ?

ps: если убираю вызов disable_int7(); из обработчика прерываний то при запуске оно срабатывает 1 раз а затем когда я "работаю энкодером" PORTB переключает состояние своих выводов что говорит о том что прерывание отрабатывает
lix
Опытный кот
Сообщения: 703
Зарегистрирован: Вс янв 17, 2010 15:32:19
Откуда: Курган

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

Сообщение lix »

acckyiboxxx, вы уверены что правильно биты в регистрах сбрасываете?
Обычно нужно инвертирование

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

 EIMSK &= ~(1<<INT7);
uk8amk
Поставщик валерьянки для Кота
Сообщения: 2222
Зарегистрирован: Вт ноя 27, 2007 11:32:06
Откуда: Tashkent

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

Сообщение uk8amk »

Разъясните пожалуйста про перечислители.
Допустим, перечислитель _flags:

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

enum _flags {
_READ =01, /* файл открыт на чтение */
_WRITE = 02, /* файл открыт на запись */
_UNBUF = 04, /* файл не буферизуется */
_EOF = 010, /* в данном файле встретился EOF */
_ERR = 020 /* в данном файле встретилась ошибка */
};
Какой смысл в названии перечислителя _flags, если оно напрямую не используется?
Обращение в коде происходит к самим константам(_READ,_WRITE и т.д.).
Аватара пользователя
Siarzhuk
Потрогал лапой паяльник
Сообщения: 353
Зарегистрирован: Вс янв 19, 2014 22:41:55

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

Сообщение Siarzhuk »

uk8amk писал(а):

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

enum _flags {
_READ =01, /* файл открыт на чтение */
[...]
};
Какой смысл в названии перечислителя _flags, если оно напрямую не используется?
Обращение в коде происходит к самим константам(_READ,_WRITE и т.д.).
enum _flags это определение типа и если нужно определить функцию принимающую, к примеру, параметр этого типа - вот тут имя и пригодится. Но по характерным признакам данного конкретного случая мы имеем дело с битами в маске - и попытка передать комбинацию битов выдаст предупреждение компиляции. Впрочем использование безымянных перечислений также не возбраняется современными стандартами и было-бы тут уместно.

Программы имеют свой жизненный цикл развития и за время разработки этот еnum _flag мог быть изначально запланирован к использованию в качестве типа, а затем по мере развития выродился в набор битов в маске. Ну а имя или забыто, либо, скорее всего, вставлено изначально, чтобы избежать проблем с портированием этого кода на компиляторы не понимающие безымянный enum.

PS: Кстати, использование подчёркивания в начале имён - прерогатива стандартной библиотеки и в своих программах такой нотации рекомендуется избегать.
Одновременным нажатием LIGHT и POWER, РП Sangean ATS-909X (ver 1.29) превращается в ATS-909XR! ;-)
uk8amk
Поставщик валерьянки для Кота
Сообщения: 2222
Зарегистрирован: Вт ноя 27, 2007 11:32:06
Откуда: Tashkent

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

Сообщение uk8amk »

Пытался ранее докопаться до истины, но везде в интернетах и учебниках только общие слова.
Например объявление типа, относящегося к контроллеру прерываний:

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

typedef enum IRQn
{
  NonMaskableInt_IRQn         = -14,    /*!< 2 Non Maskable Interrupt                             */
  MemoryManagement_IRQn       = -12,    /*!< 4 Cortex-M3 Memory Management Interrupt              */
  BusFault_IRQn               = -11,    /*!< 5 Cortex-M3 Bus Fault Interrupt                      */
бла-бла-бла
} IRQn_Type;
И далее функция, употребляющая этот параметр:

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

__STATIC_INLINE void NVIC_EnableIRQ(IRQn_Type IRQn)
{
  NVIC->ISER[((uint32_t)(IRQn) >> 5)] = (1 << ((uint32_t)(IRQn) & 0x1F)); /* enable interrupt */
}
При создании объекта и передачи параметра этого типа в функцию по идее должно резервироваться какое-то кол-во памяти для хранения в ОЗУ или стеке.
Но что выделяется под enum IRQn_Type IRQn ? Ведь это всего лишь набор возможных числовых констант, которые можно было тупо заменить #define-ами. Вот это не понятно.
Ответить

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