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

Если ваш вопрос не влез ни в одну из вышеперечисленных тем, вам сюда.
Аватара пользователя
FreshMan
Друг Кота
Сообщения: 6296
Зарегистрирован: Пн ноя 22, 2010 00:57:15
Откуда: Ukraine

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

Сообщение FreshMan »

вопрос относительно построения программы по модульному принципу
допустим в моем проэкте есть два модуля
main.c
module_1.c

по общепринятым правилам в main.c я должен прописать хидер #include "module_1.h" в котором я должен обозначить прототипы ф-ций
1)зачем в данном случае вообще нужен хидер ? ведь все файлы которые есть в проэкте с расширением с при компиляции все-равно сливаются воедино
2) почему бы тогда в хидере не писать сразу все ф-ции целиком ?
Tell Me The Truth
Реклама
Аватара пользователя
coredumped
Опытный кот
Сообщения: 838
Зарегистрирован: Вт апр 12, 2011 18:38:19
Откуда: с Земли

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

Сообщение coredumped »

FreshMan писал(а):
по общепринятым правилам в main.c я должен прописать хидер #include "module_1.h" в котором я должен обозначить прототипы ф-ций
1)зачем в данном случае вообще нужен хидер ? ведь все файлы которые есть в проэкте с расширением с при компиляции все-равно сливаются воедино
2) почему бы тогда в хидере не писать сразу все ф-ции целиком ?
#include "module_1.h" выполняется препроцессором и вызывает вставку всего содержимого файла "module_1.h" в компилируемый файл. Если Вы опишите в "module_1.h" функции полностью, а не только прототипы, то файлы скомпилятся, однако при линковке Вы получите сообщение об ошибке (что-то типа "функция с именем бла-бла объявлена несколько раз"). Это, если хидер включен в несколько модулей программы.
Поэтому, делается так: пишем функции в отдельном модуле - файле xxx.c, затем создаем хидер (xxx.h), содержащий прототипы функций, которые мы хотим использовать в других модулях, а в самих модулях делаем включение #include "xxx.h".
Включение нужно для того, чтоб компилятор понял какие именно параметры будут в функции, которая позднее будет подлинкована из других модулей. Можно вместо хидера писать в каждом модуле описание прототипа функции, например extern int my_blackbox(int a);(extern можно не писать для большинства компиляторов).
Еще оди совет: в хидерах используйте условное объявление типа #ifndef _MODULE_H_ #define _MODULE_H_ ... содержимое хидера ... #endif
Пример:

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

#ifndef __FPGA_CONF_H
#define __FPGA_CONF_H

#include "stm32f4xx.h"

#define FPGA_INIT_CYCLE		50		/* extra DCLK cycles while initialization is in progress */
#define FPGA_RECONF_COUNT_MAX	5		/* #auto-reconfiguration when error found */
  
uint8_t fpga_load(void);

#endif  /* __FPGA_CONF_H */
Это позволит избежать ошибок компиляции, если хидер включен в цепочку несколько раз. Такое бывает, если хидер включен в другие хидера... Короче используйте подобный скелет во всех хидерах, это сократит количество предупреждений и ошибок компиляции.
Все будет только лучше, в крайнем случае - хуже.
Реклама
Аватара пользователя
FreshMan
Друг Кота
Сообщения: 6296
Зарегистрирован: Пн ноя 22, 2010 00:57:15
Откуда: Ukraine

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

Сообщение FreshMan »

coredumped писал(а):Это, если хидер включен в несколько модулей программы.
а если он включен только в один модуль ?
если мой проэкт имеет только один модуль, ну окромя главного(main), то тогда можна прямо в хидере описывать полностью ф-ции ?
Tell Me The Truth
Аватара пользователя
YS
Друг Кота
Сообщения: 7518
Зарегистрирован: Вс мар 29, 2009 22:09:05
Контактная информация:

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

Сообщение YS »

то тогда можна прямо в хидере описывать полностью ф-ции ?
Можно. Но не стоит так делать - кто знает, что Вы захотите с этими файлами сделать потом... Вообще обычно модули пишут в частности и для того, чтобы использовать код повторно.
Разница между теорией и практикой на практике гораздо больше, чем в теории.
Реклама
Эиком - электронные компоненты и радиодетали
lix
Опытный кот
Сообщения: 703
Зарегистрирован: Вс янв 17, 2010 15:32:19
Откуда: Курган

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

Сообщение lix »

то тогда можна прямо в хидере описывать полностью ф-ции ?
можно, только если потом включить этот хидер более чем в один с-файл, то получите ошибку о множественом определении функций.
Реклама
Аватара пользователя
vitalik_1984
Поставщик валерьянки для Кота
Сообщения: 2482
Зарегистрирован: Пт авг 27, 2010 05:57:06
Откуда: Тюмень
Контактная информация:

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

Сообщение vitalik_1984 »

coredumped писал(а):Еще оди совет: в хидерах используйте условное объявление типа #ifndef _MODULE_H_ #define _MODULE_H_ ... содержимое хидера ... #endif
Это все правильно только чувак задал вопрос зачем они вообще нужны эти модули.
Вот ответ
YS писал(а):Вообще обычно модули пишут в частности и для того, чтобы использовать код повторно.
Так сказать для уменьшения времени разработки и тестирования программ. То есть если какая то полезная функция будет написана внутри основного файла будет очень трудно вынести данный код из общей массы. А так легко использовать модуль, который создан для выполнения одной конкретной задачи.
Так же создание отдельных файлов позволяет компилировать их отдельно, что так же позволяет сократить время разработки больших проектов. Не прибегая к полной компиляции.
Это было по первому вопросу вот еще в Вики статья
А по второму вопросу немного другая тема
Вот статья
Реклама
Аватара пользователя
Alkarax
Первый раз сказал Мяу!
Сообщения: 27
Зарегистрирован: Чт мар 21, 2013 16:22:09

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

Сообщение Alkarax »

Здравствуйте коты, разбираюсь с подключением AVR по юсб, нашел отличный проект, но теперь не могу разобраться с программой на стороне компа, в проекте есть Dll библиотека и пользовательская программа в качестве примера, но они на Delphi, а я пишу на с++ и дельфи вообще не знаю. В проекте упоминается, что данную Dll можно использовать и для с++, подскажите пожалуйста как это делается.
Вот ссылка проекта http://www.gaw.ru/html.cgi/txt/app/micr ... AVR309.htm, там же в конце все файлы.
Аватара пользователя
Kavka
Мудрый кот
Сообщения: 1810
Зарегистрирован: Чт июн 10, 2010 08:55:35
Откуда: Сибирские Афины

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

Сообщение Kavka »

Если смотрите на программную реализацию USB на AVR-ках, то лучше используйте вот эту реализацию.
http://www.obdev.at/products/vusb/index.html
Когда уже ничего не помогает - прочтите, наконец, инструкцию.
Лучший оптимизатор находится у вас между ушей. (Майкл Абраш, программист Quake и QuakeII)
Избыток информации ведёт к оскудению души - Леонтьев А. (сказано в 1965 г.)
Аватара пользователя
Alkarax
Первый раз сказал Мяу!
Сообщения: 27
Зарегистрирован: Чт мар 21, 2013 16:22:09

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

Сообщение Alkarax »

Спасибо, но тот, про который я говорю считаю лучшим, потому что там реализована сразу куча функций, не переделывая прошивки я могу делать на одном микроконтроллере конечное устройство и, самый главный плюс, здесь есть примеры всех этапов программирования от железячки до конечного пользователя. Просто я сейчас делаю курсовую, мне нужно разработать драйвер, драйвер я худо-бедно разобрал полностью, а вот dllку к нему освоить не получается никак, повторюсь в дельфи я полный 0.
Аватара пользователя
urry
Сверлит текстолит когтями
Сообщения: 1262
Зарегистрирован: Пн дек 08, 2008 10:58:48
Откуда: Винница
Контактная информация:

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

Сообщение urry »

http://forum.sources.ru/index.php?showtopic=248068
здесь находится h файл для загрузки этой длл.
Но на месте препода я бы это не принял - тема умерла лет так 10 назад. Ну скажем, утратила актуальность :)
Когда мега работает с юсб, она больше практически ни на что не отвлекается - да и делает это достаточно криво. Сейчас полно дешевых мк с аппаратным блоком юсб.
Аватара пользователя
Alkarax
Первый раз сказал Мяу!
Сообщения: 27
Зарегистрирован: Чт мар 21, 2013 16:22:09

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

Сообщение Alkarax »

Большое спасибо! Я с вами не спорю, я все собираюсь начать осваивать stm32,там и юсб и сами они посовременнее, но постоянно что-то отвлекает. На счет принял бы или нет препод, то почему нет, ведь задача стоит научиться писать драйверы, а как работает все что выше или ниже его - без разницы, это уже просто моя личная любознательность. Просто Вы не представляете в каком отсталом месте я учусь и изначально мне давали задание написать драйвер консоли для дос на ассемблере, я подумал что если уж тратить время, то на что-то хоть немного полезное и интересное. Если Вас не затруднит, можно примерчик вызова любой функции из этой библиотеки, а то везде натыкаюсь на примеры с использованием lib? И еще вопрос: по ссылке что вы дали речь идет о старой и новой версии данной dll, файл .h там как я понял к старой, а dll у меня новая, нужно мне изменять файл .h или так работать тоже будет? Или я вообще что-то не так понял?
pokk
Вымогатель припоя
Сообщения: 574
Зарегистрирован: Вт ноя 02, 2010 17:46:37

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

Сообщение pokk »

Здравствуйте, почему у меня не получается сделать обращение через точку к структуре

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

typedef struct List_IP_PORT1 {
  unsigned char   n;
  unsigned char   IP[2][4];
  unsigned int   port[2];
} List_IP_PORT;
Через указатель работает всё

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

List=(List_IP_PORT *)srt_buf;
   List->n=number;
   List->IP[0][0]=ip1[0];
   List->IP[0][1]=ip1[1];
   List->IP[0][2]=ip1[2];
   List->IP[0][3]=ip1[3];

   List->IP[1][0]=ip2[0];
   List->IP[1][1]=ip2[1];
   List->IP[1][2]=ip2[2];
   List->IP[1][3]=ip2[3];

   List->port[0]=port1;
   List->port[1]=port2;
Делаю вот так вот

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

List_IP_PORT.n=24;
Rомпилятор(IAR) ругается
Error[Pe040]: expected an identifier C:\STM32\W5100 v12(trap list)\main.c 114
Error[Pe144]: a value of type "int" cannot be used to initialize an entity of type "List_IP_PORT" C:\STM32\W5100 v12(trap list)\main.c 114

Пытаюсь разобраться в чём отличия обращения к элементам структуры через точку или стрелочку. Пока только одна мысль что через стрелочку можно структуру наложить на массив а через точку нет.
a_skr
Вымогатель припоя
Сообщения: 630
Зарегистрирован: Пн июн 14, 2010 13:07:29
Откуда: Жуковский

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

Сообщение a_skr »

List_IP_PORT - это тип. Объявите переменную вашего типа и обращайтесь через точку:
List_IP_PORT x;
x.n = 5;
Стрелочкой :) работают с указателями.
BorisSPB
Встал на лапы
Сообщения: 145
Зарегистрирован: Ср фев 01, 2012 10:55:53

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

Сообщение BorisSPB »

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

List=(List_IP_PORT *)srt_buf;
С приведением типов указателей надо быть осторожным. Элементы в структуре могут быть расположены с выравниванием и например List_IP_PORT.n может занимать не один байт, как задумывалось, а два. Поэтому если идет разбор потока байт, структуру List_IP_PORT следует определить с атрибутом __packed или подобным. А еще могут быть проблемы с выравниванием доступа к памяти процессора, об этом надо тоже не забывать.
Аватара пользователя
YS
Друг Кота
Сообщения: 7518
Зарегистрирован: Вс мар 29, 2009 22:09:05
Контактная информация:

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

Сообщение YS »

Делаю вот так вот
В Вашем случае List_IP_PORT это тип, определенный через typedef. Соответственно, ему ничего нельзя присвоить. :) На доступном примере: это все равно, что написать int=2.

Как сказали выше, надо объявить переменную этого типа и использовать ее. :)

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

List_IP_PORT my_list;

...

my_list.n=24;

...
Разница между теорией и практикой на практике гораздо больше, чем в теории.
Аватара пользователя
isx
Поставщик валерьянки для Кота
Сообщения: 2316
Зарегистрирован: Вс июн 26, 2011 20:03:21

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

Сообщение isx »

Вечер добрый!
Помогите пожалуйста справиться с 74HC595. Написал код для проверки, но он не пашет. Подскажите пожалуйста, где ошибка?

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



 if (b1 == 0) { 
 PORTB.2 = 0x00;  //ST
 PORTB.0 = 0x00;  //SH
 PORTB.3 = 0x00;  //MR
 delay_us(2);
 PORTB.3 = 0x01;   //MR
 for ( x1=0;x1<8;x1++) { 
PORTB.1 = AA1[x1];     // char AA1[8] = {0,0,0,1,0,0,0,0};
PORTB.0 = 0x01;   //SH
delay_us(2);
PORTB.0 = 0x00;  //SH   
}
b1 = 1; 
PORTB.2 = 0x01; //ST
delay_us(2);
PORTB.2 = 0x00; //ST



} 
  
 else {PORTB.3 = 0x00;}   //MR    
Пардон :)
Код рабочий, я просто не соединил в протеусе пин OE на землю. Щас наткнулся только на статью, где такое действие описано...
Аватара пользователя
YS
Друг Кота
Сообщения: 7518
Зарегистрирован: Вс мар 29, 2009 22:09:05
Контактная информация:

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

Сообщение YS »

Скажу честно - мне лень анализировать, где конкретно ошибка. :) Давайте я покажу, как это работает у меня...
Спойлер

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

#include <avr/io.h>
#include <util/delay.h>
#include <stdint.h>

#define HC_PORT		PORTD
#define HC_DDR		DDRD
#define HC_ST		(1<<PD6)
#define HC_SH		(1<<PD7)
#define HC_DS		(1<<PD5)

void HC_InitLines(void)
{
  HC_DDR|=HC_DS | HC_ST | HC_SH;
  HC_PORT&=~(HC_DS | HC_ST | HC_SH);
}

void HC_ShiftByte(uint8_t b)
{
  uint8_t msk;

  HC_PORT&=~HC_ST;

  for (msk=0x80; msk; msk=msk >> 1)
  {
    HC_PORT&=~HC_SH;

    if (b & msk)
	{
	  HC_PORT|=HC_DS;
	}
	else
	{
	  HC_PORT&=~HC_DS;
	}

	HC_PORT|=HC_SH;
  }

  HC_PORT|=HC_ST;
}

void main(void)
{
  HC_InitLines();

  while (1)
  {
    HC_ShiftByte(0x55);
	_delay_ms(500);
	HC_ShiftByte(0xAA);
	_delay_ms(500);
  }
}
Щас наткнулся только на статью, где такое действие описано...
Вообще, начинать изучение любой микросхемы принято с официальной документации. :wink:
Разница между теорией и практикой на практике гораздо больше, чем в теории.
Аватара пользователя
isx
Поставщик валерьянки для Кота
Сообщения: 2316
Зарегистрирован: Вс июн 26, 2011 20:03:21

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

Сообщение isx »

YS писал(а):
Вообще, начинать изучение любой микросхемы принято с официальной документации. :wink:
Был бы мой английский столь совершенен, чтоб разобрать без бутылки что там написано... :))
pokk
Вымогатель припоя
Сообщения: 574
Зарегистрирован: Вт ноя 02, 2010 17:46:37

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

Сообщение pokk »

Благодарю за помощь теперь стало понятнее.
BorisSPB писал(а):С приведением типов указателей надо быть осторожным
В данном примере это не сильно важно но вот в другой структуре это критично. Но пока всё работает стабильно если что отвалится буду знать куда копать.(Я так понял что отвалится она может при смене компилятора или если в настройках выравнивания структуры похимичить ?)

И ещё не большой вопросик появился если надо передать в функцию много параметров штук 10 как это сделать правильно ?
Причём из этих 10 штуки 2-3 это массивы. Если всё в лоб то она большая сильно становится.
По пробовал эти все параметры запихать в структуру и в функцию только структуру передавать. Но всё равно перед функцией
все эти данные объявить. Хотя мне так больше нравится.

А как быть с таким вот случаем

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

typedef struct Setting {
  u8_t community[20];
  u8_t n;
} Setting;
если содержимое массива community меньше 20 к примеру 10 занимается остальное нули. как сделать что бы вместо нулей была переменная n ? думал сделать вот такое но адрес community почему-то 0.

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

typedef struct Setting {
  u8_t *community;
  u8_t n;
} Setting;
Аватара пользователя
coredumped
Опытный кот
Сообщения: 838
Зарегистрирован: Вт апр 12, 2011 18:38:19
Откуда: с Земли

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

Сообщение coredumped »

Если размер массива меняется, то логично использовать указатель, как Вы написали, однако указателю нужно присвоить значение - адрес массива. Те сначала нужно выделить память под массив, а потом присвоить адрес этой памяти массиву. Механизмы выделения-освобождения памяти отличаются от операционной системы, под которую пишется программа. Вот пример под Linux с Вашей структурой

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

typedef struct Setting {
  u8_t *community;
  u8_t n;
} Setting;

Settings.community = malloc(100); // Выделяем 100 байт
// ...........
free(Settings.community); // Освобождаем ранее выделенную память

Таким образом мы имеем дело с динамически выделяемой памятью или "динамической памятью" (еще используется термин "куча").
Для МК тоже есть реализации упрощенного управления динамической памятью, однако в отличии от "взрослых" ОС память может выделяться из заранее отведенной области и только непрерывным блоком. Обсуждение механизмов управления динамической памятью заслуживает целой книги.
Можете погуглить словам malloc, heap.
PS: если Вы имеете дело с маленьким МК и памяти хватает, проще выделить статический массив с запасом, чем возиться с перераспределением памяти. Тут делема: производительность - расход памяти. Я советую использовать танцы с динамическим распределением, если памяти не хватает (в случае МК, естественно). Есть много методов оптимизации использования памяти, но все они приводят к снижению скорости выполнения программы.
Все будет только лучше, в крайнем случае - хуже.
Ответить

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