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

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

Сообщение ARV »

ROMan2947 писал(а):с понятиями определена, описана,объявлена, инициализирована одни путаницы.
это плохо.
если своими словами, то:
1. каждая сущность программы на Си может быть ОПИСАНА, РЕАЛИЗОВАНА и ИСПОЛЬЗОВАНА.
2. описана (объявлена) - это значит, что компилятор уведомлен о том, что в программе такая сущность МОЖЕТ существовать. где - пока не ясно
3. реализация сущности - это команда компилятору выделить память и(возможно) заполнить её какими-то данными. теперь эта сущность существует на самом деле.
4. использование - это работа с описанной и реализованой сущностью.
5. описание, реализация и использование могут быть не все сразу, а частично, минимально необходимый вариант - реализация, если её нет - считай, все остальное смысла не имеет
6. любое использование должно быть после реализации, любая реализация - после описания. и никак иначе. при этом реализация заменяет собой описание, т.е. при наличии реализации описание становится необязательным. но при наличии описания не обязательна реализация.

под сущностью я подразумеваю любую элементарную конструкцию языка Си: тип, переменную, структуру, функцию. макрос не является в строгом понимании элементом языка Си (это к препроцессору относится), и поэтому не в полной мере удовлетворяет этому описанию.

примеры

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

extern int var; // описание переменной
int var; // реализация переменной
var = 12; // использование переменной

int foo(void); // описание функции
int foo(void){
  return 12;
} // реализация функции

var = foo(); // использование функции
разве тут есть путаница?
если рассматривать человека снизу, покажется, что мозг у него глубоко в жопе
при взгляде на многих сверху ничего не меняется...

Мой уютный бложик... заходите!
Контактная информация:
Реклама
Грызет канифоль
Аватара пользователя
Сообщения: 287
Зарегистрирован: Сб янв 23, 2016 00:59:59
Откуда: Чебоксары

Сообщение ROMan2947 »

[uquote="ARV",url="/forum/viewtopic.php?p=3337095#p3337095"]примеры

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

extern int var; // описание переменной
int var; // реализация переменной
разве тут есть путаница?[/uquote] Страшно тонкая грань :roll:
Реклама
ARV
Ум, честь и совесть. И скромность.
Аватара пользователя
Сообщения: 18787
Зарегистрирован: Чт дек 28, 2006 08:19:56
Откуда: Новочеркасск

Сообщение ARV »

ничего тонкого: первая строка просто рассказывает, что где-то там (extern - вовне, снаружи) переменная типа int и идентификатором var МОЖЕТ БЫТЬ ЕСТЬ.
вторая явно показывает, что эта переменная ЕСТЬ.

другое дело, что часто применяют термин ОПРЕДЕЛЕНА вместо РЕАЛИЗОВАНА, подразумевая, что определенность - признак существования, но фактически это не корректно (хотя и широко используется). например, никогда не говорят об ОПРЕДЕЛЕНИИ методов класса, но только о РЕАЛИЗАЦИИ (это уже из С++, но сути не меняет). поэтому я сам для себя использую вышеприведенную классификацию, меня понимают все программисты, а я не путаюсь. чего и вам желаю.
если рассматривать человека снизу, покажется, что мозг у него глубоко в жопе
при взгляде на многих сверху ничего не меняется...

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

Сообщение ROMan2947 »

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

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

typedef struct  
{
      TvvPtr PtrGWS;           // пункт меню на первом уровне
      TvvPtr PtrHWS;           // пункт меню на первом уровне
}Level1;   //---тип структуры 1 уровня   

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

Level1 MeNU_LEVEL1;
- это уже реализация так как компилятор выделяет память для структуры MeNU_LEVEL1 типа Level1 это должно находиться в исходнике модуля

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

Level1 MeNU_LEVEL1={output_level_1_GWS,output_level_1_HWS};
это использование и тоже должен быть в исходнкие

правильно мыслю?

Добавлено after 1 minute 59 seconds:
[uquote="ARV",url="/forum/viewtopic.php?p=3337107#p3337107"]чего и вам желаю.[/uquote]
Спасибо! :beer: подкинули лошадиную долю над чем поразбираться.
Реклама
Эиком - электронные компоненты и радиодетали
ARV
Ум, честь и совесть. И скромность.
Аватара пользователя
Сообщения: 18787
Зарегистрирован: Чт дек 28, 2006 08:19:56
Откуда: Новочеркасск

Сообщение ARV »

ROMan2947 писал(а):Т.е мы дали понять компилятору, что возможно есть такой тип
нет, тип в момент описания уже существует, для него два этапа (описание и реализация) неразделимы по по определению, т.к. тип - это не материальное явление, а описательное.
ROMan2947 писал(а):правильно мыслю?
в общем и целом - да, но по-моему, Си не позволяет производить присваивания переменным структурного типа кроме как в момент реализации.

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

Level1 MeNU_LEVEL1={output_level_1_GWS,output_level_1_HWS};
такое можно написать в секции ОПРЕДЕЛЕНИЯ/ОПИСАНИЯ, но не внутри функции на этапе ИСПОЛЬЗОВАНИЯ.
если рассматривать человека снизу, покажется, что мозг у него глубоко в жопе
при взгляде на многих сверху ничего не меняется...

Мой уютный бложик... заходите!
Контактная информация:
Реклама
Грызет канифоль
Аватара пользователя
Сообщения: 287
Зарегистрирован: Сб янв 23, 2016 00:59:59
Откуда: Чебоксары

Сообщение ROMan2947 »

[uquote="ARV",url="/forum/viewtopic.php?p=3337120#p3337120"][quote="ROMan2947"] но по-моему, Си не позволяет производить присваивания переменным структурного типа кроме как в момент реализации.[/uquote]да верно!

так нельзя!

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

Level1 MeNU_LEVEL1;
MeNU_LEVEL1={output_level_1_GWS,output_level_1_HWS};

а так можно!

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

Level1  MeNU_LEVEL1=    {output_level_1_GWS,output_level_1_HWS};
P.S. как можно все это знать :dont_know:
Реклама
ARV
Ум, честь и совесть. И скромность.
Аватара пользователя
Сообщения: 18787
Зарегистрирован: Чт дек 28, 2006 08:19:56
Откуда: Новочеркасск

Сообщение ARV »

ROMan2947 писал(а):как можно все это знать
зададите этот вопрос самому себе примерно через годик :)
если рассматривать человека снизу, покажется, что мозг у него глубоко в жопе
при взгляде на многих сверху ничего не меняется...

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

Сообщение ROMan2947 »

[uquote="ARV",url="/forum/viewtopic.php?p=3337132#p3337132"]зададите этот вопрос самому себе примерно через годик :)[/uquote]Дай Бог :roll:
Грызет канифоль
Аватара пользователя
Сообщения: 287
Зарегистрирован: Сб янв 23, 2016 00:59:59
Откуда: Чебоксары

Сообщение ROMan2947 »

Здравствуйте! Работу модуля опроса клавиатуры нужно отладить с основным модулем.
1) Опрос клавиатуры происходит по таймеру. Где нужно помещать обработчик прерывании, в основном модуле или же в исходнике модуля клавиатуры? На практике пока разницы не заметил.На данный момент обработчик я поместил в исходник главного модуля.
2) Имеется переменная BuTTOn,она объявлена в исходнике главного модуля.при прерывании по таймеру я передаю ее адрес в функцию опроса в модуль клавиатуры. Там по ее адресу присваиваю код кнопки. По выходу из прерывания идет проверка на наличие в переменной BuTTON кода,при ее наличии передаю адрес этой переменной в модуль Меню.Компилируется все хорошо,ошибок нет.Отладчиком проходил, программа производит опрос кнопок и правильно присваивает переменной BuTTON код нажатой кнопки. но не переходит в модуль меню.
3) В чем разница использования внешней переменной и работать просто с адресом переменной? я работаю с адресом переменной в сторонних модулях и ниче вроде все работает как надо.
main.h
Спойлер

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

#ifndef MAIN_H_
#define MAIN_H_
#define F_CPU 8000000UL
#include <avr/io.h>
#include <stdio.h>
#include <avr/delay.h>
#include <avr/interrupt.h>
#include <stdint.h>

#endif /*MAIN_H_*/
main.c
Спойлер

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

#include "main.h"
#include "Menu_v2.0.c"
#include "Menu_v2.0.h"
#include "KEY.c"
#include "KEY.h"

uint8_t BuTTON;

ISR(TIMER0_COMP_vect)
{
	key(&BuTTON);
}

int main(void)
{
//--- инициализация---------------------------------------------------------
	  KEY_init();
	  sei();
	while (1)
	{
		
		if(BuTTON)
		{
			opredelenieUkazatela(&BuTTON);
		} 
		
	}
}
KEY.h
Спойлер

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

#ifndef KEY_H_
#define KEY_H_ 

#define KEY_DDR_OUT DDRD
#define KEY_PORT_OUT PORTD

#define KEY_DDR_IN DDRC
#define KEY_PORT_IN PORTC
#define KEY_PIN PINC

#define stroka_1  7
#define stroka_2  6
#define stolbec_1 6
#define stolbec_2 7
#define DREBESK   0x50

#define Enter  0x90   //10010000
#define Cancel 0x60   //01100000
#define DN     0x50   //01010000
#define UP     0xA0   //10100000

void KEY_init(void);      // инициализация клавиатуры
void key(uint8_t*);       // функция опроса клавиатуры
#endif

KEY.c
Спойлер

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

#include "KEY.h"
#include "main.h"


uint8_t RES=0;

//-------инициализация клавиатуры и таймера Т0-----------------------------
void KEY_init(void)
{
	KEY_DDR_IN &=~((1<<stolbec_1)|(1<<stolbec_2));
	KEY_PORT_IN|=(1<<stolbec_1)|(1<<stolbec_2);

	KEY_DDR_OUT |=(1<<stroka_1)|(1<<stroka_2);
	KEY_PORT_OUT|=(1<<stroka_1)|(1<<stroka_2);
	TCCR0|=(1<<WGM01)|(1<<CS01)|(1<<CS00); // режим СТС, предделитель 8
	TIMSK|=(1<<OCIE0);                     // включение прерывания при совпадении
	TCNT0=0;
	OCR0=254;
	
}
//-------------------------------------------------------------------------



void key(uint8_t*BuTTON_key)
{
	uint8_t buffer=0;
	static uint8_t  count =0;
	
	for(char i=stroka_1; i>=stroka_2;i--)
	{
		
		for(char i=stroka_1; i>=stroka_2;i--)
		{
			
			KEY_PORT_OUT&=~(1<<i);
			RES=(KEY_PORT_OUT&0xC0)|((KEY_PIN&0xC0)>>2);
			KEY_PORT_OUT|=1<<i;

			switch (RES)
			{
				case Enter : buffer=Enter  ;break;
				case Cancel: buffer=Cancel ;break;
				case UP    : buffer=UP     ;break;
				case DN    : buffer=DN     ;break;
			}
		}
		if(buffer)
		{
			if(count==DREBESK)
			{
	            (*BuTTON_key)=buffer;
				buffer=0;
				count=0;
				//TIMSK&=~(1<<OCIE0);
			}
			else count++;
		}
		else count=0;

	}

}




Говорящий с текстолитом
Аватара пользователя
Сообщения: 1590
Зарегистрирован: Вс июн 24, 2012 16:07:00
Откуда: Лен.Обл.

Сообщение da-nie »

Где нужно помещать обработчик прерывании, в основном модуле или же в исходнике модуля клавиатуры?
Там, где он логически согласуется с принятой структурой программы. Если у вас принято все обработчики держать в главном модуле, то там. А если вы их хотите держать в модулях (с логикой подобное к подобному), то держите там.
Имеется переменная BuTTOn,она объявлена в исходнике главного модуля.при прерывании по таймеру я передаю ее адрес в функцию опроса в модуль клавиатуры. Там по ее адресу присваиваю код кнопки.
Вам нужен модификатор volatile при объявлении переменной BuTTOn. Компилятор не знает, что эта переменная может измениться где-то ещё, потому способен "оптимизировать" все обращения к этой переменной. Ну и красиво было бы запрещать прерывания при работе с переменной в основном потоке.
В чем разница использования внешней переменной и работать просто с адресом переменной? я работаю с адресом переменной в сторонних модулях и ниче вроде все работает как надо.
Работайте так, как вам удобно. Правда, смысла передавать адрес нет никакого в вашем случае. Объявите переменную как extern в модулях, её использующих, и она станет там доступна как обычно, по имени. Я так понимаю, вы именно из-за недоступности этой переменной в key.c и придумали передавать адрес?
И день и ночь в пути...
Мои программки: https://github.com/da-nie
Мои публикации: https://habr.com/ru/users/da-nie/posts/
Мои видео: https://www.youtube.com/channel/UCUroi3 ... 52g/videos
Контактная информация:
Грызет канифоль
Аватара пользователя
Сообщения: 287
Зарегистрирован: Сб янв 23, 2016 00:59:59
Откуда: Чебоксары

Сообщение ROMan2947 »

Там, где он логически согласуется с принятой структурой программы. Если у вас принято все обработчики держать в главном модуле, то там. А если вы их хотите держать в модулях (с логикой подобное к подобному), то держите там
Для меня логичнее ее держать в модуле клавиатуры,т.к. обработчик относиться к клавиатуре.Я хотел узнать наличие разницы кроме как логики.
Вам нужен модификатор volatile при объявлении переменной BuTTOn. Компилятор не знает, что эта переменная может измениться где-то ещё, потому способен "оптимизировать" все обращения к этой переменной.
Учту!Хотя изменения этой переменной происходят без проблем, да и предупреждение думаю было бы,а его нет.
Ну и красиво было бы запрещать прерывания при работе с переменной в основном потоке.
Понял!
И имейте в виду вот что - компилятор не обязан все инструкции выполнять по-порядку.
как это не обязан :shock: :shock: :shock:
это же страшно важно!!!
Я так понимаю, вы именно из-за недоступности этой переменной в key.c и придумали передавать адрес?
Нет! просто пока мне не совсем понятна работы c extern на практике, а с указателями понятно, вот решил работать с ними.
Говорящий с текстолитом
Аватара пользователя
Сообщения: 1590
Зарегистрирован: Вс июн 24, 2012 16:07:00
Откуда: Лен.Обл.

Сообщение da-nie »

Для меня логичнее ее держать в модуле клавиатуры,т.к. обработчик относиться к клавиатуре.Я хотел узнать наличие разницы кроме как логики.
Тогда там и держите. :) Разницы никакой.
как это не обязан :shock: :shock: :shock: это же страшно важно!!!
Вот чтобы вас не пугать и не запутать, я и стёр то, что написал. :)
Не беспокойтесь - для вашего прерывания это не важно - пока вы не выйдете из прерывания, основная программа не продолжится. Но в настоящих многопоточных приложениях просто имейте это в виду. ;) Подробности вы прочтете в "Барьеры памяти и компилятора". Например, тут: http://scrutator.me/post/2015/05/16/mem ... riers.aspx
Нет! просто пока мне не совсем понятна работы c extern на практике, а с указателями понятно, вот решил работать с ними.
На практике в модуле key.h вы пишете после #include
extern uint8_t BuTTON;

И дальше работаете с этой переменной, как с глобальной.
Учту!Хотя изменения этой переменной происходят без проблем, да и предупреждение думаю было бы,а его нет.
Предупреждения и не будет. Это не ошибка. Кстати, у вас этот самый BuTTON стоит инициализировать.
Фишка в том, что вот это:

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

if(BuTTON)
      {
         opredelenieUkazatela(&BuTTON);
      } 
после компиляции (не в Debug-конфигурации!) превратится в:

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

if(0)
      {
         opredelenieUkazatela(&BuTTON);
      } 

И будет выброшено из программы. А что? BuTTON внутри цикла не меняется.
И день и ночь в пути...
Мои программки: https://github.com/da-nie
Мои публикации: https://habr.com/ru/users/da-nie/posts/
Мои видео: https://www.youtube.com/channel/UCUroi3 ... 52g/videos
Контактная информация:
Грызет канифоль
Аватара пользователя
Сообщения: 287
Зарегистрирован: Сб янв 23, 2016 00:59:59
Откуда: Чебоксары

Сообщение ROMan2947 »

Тогда там и держите. :)
перенес и сразу понадобилось использовать extern!В обработчике то не видать адреса BuTTON.

Вот чтобы вас не пугать и не запутать, я и стёр то, что написал. :)
Не беспокойтесь - для прерываний это не важно - пока вы не выйдете из прерывания, основная программа не продолжится. Но в настоящих многопоточных приложениях просто имейте это в виду. ;) Подробности вы прочтете в "Барьеры памяти и компилятора". Например, тут: http://scrutator.me/post/2015/05/16/mem ... riers.aspx
Ознакомлюсь спасибо!!

На практике в модуле key.h вы пишете после #include
extern uint8_t BuTTON;

И дальше работаете с этой переменной, как с глобальной.

После #include пишем extern uint8_t BuTTON; ???
попробовал без #include видится нормально.
Предупреждения и не будет. Это не ошибка. Кстати, у вас этот самый BuTTON стоит инициализировать.
Инициализировал!
Говорящий с текстолитом
Аватара пользователя
Сообщения: 1590
Зарегистрирован: Вс июн 24, 2012 16:07:00
Откуда: Лен.Обл.

Сообщение da-nie »

перенес и сразу понадобилось использовать extern!В обработчике то не видать адреса BuTTON.
Это нормально. :)
После #include пишем extern uint8_t BuTTON; ???
попробовал без #include видится нормально.
Не-не, я имел в виду, в машем модуле после написанных #include. :)

А заработало? Кнопки-то работают?
И день и ночь в пути...
Мои программки: https://github.com/da-nie
Мои публикации: https://habr.com/ru/users/da-nie/posts/
Мои видео: https://www.youtube.com/channel/UCUroi3 ... 52g/videos
Контактная информация:
Грызет канифоль
Аватара пользователя
Сообщения: 287
Зарегистрирован: Сб янв 23, 2016 00:59:59
Откуда: Чебоксары

Сообщение ROMan2947 »

Вам нужен модификатор volatile при объявлении переменной BuTTOn.
Интересное явление! При опросе кнопки по прерыванию я не мог перейти в меню, хотя в отладчике все прекрасно было видно значение BuTTON оно соответствовало для перехода,но не происходило.Заем функцию опроса поместил в основной цикл и запретил прерывания. Переход в меню происходил отлично, но мне нужно это делать в прерывании. Вернул все обратно в обработчик и добавил volatile к BuTTON, и о чудо,все заработало!! :)))
Спасибо огромное очень полезными вещами поделились :beer:
Говорящий с текстолитом
Аватара пользователя
Сообщения: 1590
Зарегистрирован: Вс июн 24, 2012 16:07:00
Откуда: Лен.Обл.

Сообщение da-nie »

Спасибо огромное очень полезными вещами поделились
Вот вам будет ещё полезнее почитать:
Archive.zip
(507.46 КБ) 263 скачивания
:)
И день и ночь в пути...
Мои программки: https://github.com/da-nie
Мои публикации: https://habr.com/ru/users/da-nie/posts/
Мои видео: https://www.youtube.com/channel/UCUroi3 ... 52g/videos
Контактная информация:
Грызет канифоль
Аватара пользователя
Сообщения: 287
Зарегистрирован: Сб янв 23, 2016 00:59:59
Откуда: Чебоксары

Сообщение ROMan2947 »

Вот вам будет ещё полезнее почитать:
со вступления уже понял, это то что надо! :write: спасибо!
Говорящий с текстолитом
Аватара пользователя
Сообщения: 1590
Зарегистрирован: Вс июн 24, 2012 16:07:00
Откуда: Лен.Обл.

Сообщение da-nie »

Только не воспринимайте, как догму эти статьи. ;) Особенно в части оформления программы.
Ну и могу ещё посоветовать систему контроля версий поставить. Например, модный сейчас Git (с графическим интерфейсом, например, мне нравится Git Extension). Но это для мелких проектов, возможно, особого смысла не имеет, но для крупных и ветвящихся - это спасение от кучи версий программы. :tea:
И день и ночь в пути...
Мои программки: https://github.com/da-nie
Мои публикации: https://habr.com/ru/users/da-nie/posts/
Мои видео: https://www.youtube.com/channel/UCUroi3 ... 52g/videos
Контактная информация:
Потрогал лапой паяльник
Аватара пользователя
Сообщения: 353
Зарегистрирован: Вс янв 19, 2014 22:41:55

Сообщение Siarzhuk »

[uquote="ROMan2947",url="/forum/viewtopic.php?p=3338622#p3338622"]Где нужно помещать обработчик прерывании,[/uquote]
Там, где это позволит свести к минимуму внешние связи модуля. Чем меньше из него "торчит" наружу, тем надёжнее и предсказуемее работа. extern в чистой С-программе - это форс-мажор - давить нещадно, для функций он бессмысленен, для переменных - даёт всем кому не лень такую свободу обращения с вашими данными, которой окружающие не заслуживают, да и делает переменную уже никак не вашей - потому как контроля над тем, кто с ней побаловался, когда и как - у вас уже не будет. Резюме перфекциониста: Обработчик - в модуль клавиатуры вместе с известной переменной, которую делаем статической а кто хочет её почитать - пожалте им функцию get_cur_button. Ну и сказать оптимизатору - "Выноси, родима-а-й!"

[uquote="ROMan2947",url="/forum/viewtopic.php?p=3338622#p3338622"]В чем разница использования внешней переменной и работать просто с адресом переменной?[/uquote]
Теоретически [для встроенных типов размером меньше размера указателя] - в дополнительной операции разыменования для получения содержимого по адресу. Практически - скорее всего, компилятор и так будет оперировать указателем. Ну и для ясности понимания кода, тот кто будет его читать после вас наверняка подумает, что есть причина использования именно указателя вместо переменной - и потратит время на поиски этой причины. Пишите проще - и сами-же себе спасибо скажете через пару годиков, будь придётся нынешний код ещё куда встраивать.

Добавлено after 6 minutes 7 seconds:
[uquote="da-nie",url="/forum/viewtopic.php?p=3338694#p3338694"]Ну и могу ещё посоветовать систему контроля версий поставить.[/uquote]
Настойчиво посоветовать. :-)
Одновременным нажатием LIGHT и POWER, РП Sangean ATS-909X (ver 1.29) превращается в ATS-909XR! ;-)
Грызет канифоль
Аватара пользователя
Сообщения: 287
Зарегистрирован: Сб янв 23, 2016 00:59:59
Откуда: Чебоксары

Сообщение ROMan2947 »

[uquote="da-nie",url="/forum/viewtopic.php?p=3338694#p3338694"]Ну и могу ещё посоветовать систему контроля версий поставить.[/uquote] пока не представляю,что это,но попробую разобраться :tea:
для переменных - даёт всем кому не лень такую свободу обращения с вашими данными, которой окружающие не заслуживают, да и делает переменную уже никак не вашей - потому как контроля над тем, кто с ней побаловался....
что это значит? если я эту переменную никак не использую по делу,как может программа к ней добраться и побпловаться?
Обработчик - в модуль клавиатуры вместе с известной переменной, которую делаем статической

что даст static.? то что только по делу можно ее поменять?т.е конкретно там где ее используют?
Практически - скорее всего, компилятор и так будет оперировать указателем
. Тоже так предполагал, казалось этими действиями я понижаю уровень языка!
Ответить

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