Так это надо делать (умножать/делить) в основном файле, а в библиотеку передать результат. На то она и библиотека. Иначе в другим проекте можете напороться на то, что эти задефайненные выражения придётся править в библиотеке.Если я умножаю/делю/складываю дефайновские константы, то все эти операции делает препроцессор и в код ничего не идет
Вопросы по С/С++ (СИ)
- Реклама
Ничего в дефайнах не вычисляется. Дефайны только подменяют один текст на другой, и всё.aam писал(а):Если я умножаю/делю/складываю дефайновские константы, то все эти операции делает препроцессор и в код ничего не идет.
Код:
Код: Выделить всё
#define a 10
int b=a*100;
Код: Выделить всё
int b=10*100;
Да, препроцессор только подставляет текст.
А уже дальше работает оптимизация у компилятора. И результаты арифметических действий над константами представляются в виде одной константы.
Вот я эксперимент даже провёл. main.c:
Результат работы препроцессора (gcc -E), исключая то, что было подставлено из #include <stdio.h>:
А уже дальше работает оптимизация у компилятора. И результаты арифметических действий над константами представляются в виде одной константы.
Вот я эксперимент даже провёл. main.c:
Код: Выделить всё
#include <stdio.h>
#define A 2
#define B 3
#define C (A + B)
int main(void)
{
printf("%d\n", C);
return 0;
}Код: Выделить всё
int main(void)
{
printf("%d\n", (2 + 3));
return 0;
}Извиняюсь, выразился не правильно - компилятор вычисляет, но естественно код для констант не генерит.
А что за ошибка e27 ?
А что за ошибка e27 ?
у вас в двух модулях LED_menu и RC5 объявляется одна и та же переменная RC5_bit_cntaam писал(а):Код: Выделить всё
Error[e27]: Entry "RC5_bit_cnt" in module LED_menu ( c:\firmware844\Debug\Obj\LED_menu.r90 ) redefined in module RC5 ( c:\firmware844\ Debug\Obj\RC5.r90 )
Ставим плюсы: )
- Реклама
Какое расточительство... Ерунда все это. С таким подходом на ассемблере пишите.
Насчет тини13 - если используется такой МК, то к нему можно специальный подход применить.
Насчет ошибки - вероятно вы не воспользовались рекомендациями, защищающими от множественного инклюда
Насчет тини13 - если используется такой МК, то к нему можно специальный подход применить.
Насчет ошибки - вероятно вы не воспользовались рекомендациями, защищающими от множественного инклюда
Да вот не объявлена... Хотя до того как стал с h-файломи и сишниками разбираться, все компилировалось 
Всем воспользовался конечно. Типа так:
В сишниках естественно этого нет.
Я вот что-то не вдуплю, а я могу вообще глобальные переменные объявлять в нескольких h-файлах?? Скажем, в одной библиотеке объявил, в другой объявил, в главном h-файле проги объявил...
Че-то байда полная выходит... И мне начинает казаться что из-за этого именно((
И что интересно, логично - что в главном модуле он находит глобальную переменную из библиотки RC5/
Всем воспользовался конечно. Типа так:
Код: Выделить всё
#ifndef _RC5_H_INCLUDED_
#define _RC5_H_INCLUDED_ 1
.....
#endif
Я вот что-то не вдуплю, а я могу вообще глобальные переменные объявлять в нескольких h-файлах?? Скажем, в одной библиотеке объявил, в другой объявил, в главном h-файле проги объявил...
Че-то байда полная выходит... И мне начинает казаться что из-за этого именно((
И что интересно, логично - что в главном модуле он находит глобальную переменную из библиотки RC5/
Разные переменные я надеюсь?aam писал(а):Я вот что-то не вдуплю, а я могу вообще глобальные переменные объявлять в нескольких h-файлах??
Вообще зачем переменные объявлять в h файле? Если переменная глобальная, она должна быть прописана в h файл как extern. А объявлять ее надо в с файлах.
На то она и глобальная. Во всех модулях она будет видна. Если нужна переменная только в одном модуле, ее следует объявить как staticaam писал(а):И что интересно, логично - что в главном модуле он находит глобальную переменную из библиотки RC5/
Естественно!BCluster писал(а):Разные переменные я надеюсь?
Да и вообще эта переменная объявлена только в одном месте в проге.
Так, а что тогда модулем считать? Насколько я понимаю, есть сегмент данных - в нем глобальные переменные. Есть стек - в нем создаются локальные, т. е. те, которые объявлены внутри функции. Если я внутри функции заюзал спецификатор статик, то переменная тоже локальная, только что лежит в сегменте данных.
Что же касается глобальных, то как я понял, все что объявлено вне функций - глобально.
Т. е. написал я в сишнике: unsigned char a; - ее будет видно из любой другой функции. Но видно ли из другого файла?
Еще вопрос: если у меня там инлайн-функции в разных библиотеках, а компилятор по отдельности компилит сишники и потом модули собирает линкер. То как функции будут инлайниться? А ведь у меня полно в проге "одноразовых" функций типа Init_MCU() или sys_loop() и т. п. которые вызываются во всей проге только 1 раз и в 1 месте и созданы только для того, чтоб не снесло башню от объема и вида кода - чисто чтоб читаемо было. А ведь компилер там push/pop в каждую напихает непонятно нахрена.
- Сообщения: 7518
- Зарегистрирован: Вс мар 29, 2009 22:09:05
Объявлять - да. Определять - нет.Я вот что-то не вдуплю, а я могу вообще глобальные переменные объявлять в нескольких h-файлах??
Как понимает компилятор:
Код: Выделить всё
extern uint8_t foo;
Код: Выделить всё
uint8_t foo;
Первая конструкция в заголовочных файлах допустима и правильна, вторая - нет. Ибо как только компилятор натыкается на определение переменной, он пытается завести ее, выделить память и т.п. Разумеется, если он находит две переменные с одинаковым именем, он изумляется и выкидывает ошибку.
Потому заводят переменные в .c-файлах, а объявляют - в .h.
Да, если эту переменную не объявить, ВНЕЗАПНО, как static.unsigned char a; - ее будет видно из любой другой функции. Но видно ли из другого файла?
Комплект .c + .h.а что тогда модулем считать?
Если файл, в котором она объявлена, включается в две единицы компиляции - то считайте, что она объявлена два раза. Видимо, у вас так и есть.переменная объявлена только в одном месте в проге.
Разница между теорией и практикой на практике гораздо больше, чем в теории.
Добавляете в заголовочник extern unsigned char a; и везде, где он подключен, переменную будет видно.Т. е. написал я в сишнике: unsigned char a; - ее будет видно из любой другой функции. Но видно ли из другого файла?
Тут интересный момент: если инлайн-функция встречается в коде один раз, при включенной оптимизации ничто не мешает компилятору включить её в общую простыню инструкций. Не знаю, как обстоит на самом деле, надо почитать.А ведь компилер там push/pop в каждую напихает непонятно нахрена.
Возможно, переменная объявлена в .h-файле (хотя так делать не стоит, h-файлы предназначены для объявлений функций, дефайнов и описания структур). И этот файл инклюдится сразу двумя c-файлами. Соответственно, линкер видит сразу две глобальные переменные с одним именем.
Все что объявлено вне фигурных скобок!!aam писал(а):Что же касается глобальных, то как я понял, все что объявлено вне функций - глобально.
смысл таковBCluster писал(а):Так, а что тогда модулем считать?
проект разбивается на функциональные блоки
например
- инициализация портов(init.h, init.c)
- измерение температуры(temp.h, temp.c)
- отсчет времени(time.h, time.c)
- вывод на дисплей(LCD.h, LCD.c)
и естественно главный модуль проекта(projectname.c), projectname.h в принципе не нужен. т.к. все объявления осуществляются в модулях
в xxx.h соответсвующих модулей объявляются характерные для них функции, в xxx.с эти функции реализуются
в главный проект включаются заголовки модулей, объявляются глобальные переменные, и собственно реализуется функционал всего проекта
Коктейль "Рекурсивный": 20% спирта, 30% воды, 50% коктейля "Рекурсивный"...
Так у меня есть переменные, которые относятся не к какой-то конкретной функции, а ко всему девайсу.
И соответственно у меня есть файл main.c и projectname.h к нему. В этом h все общие переменные, инклюды и дефайны.
Специально сделал поиск по всем файлам - запись вида "unsigned char a;" есть только в файле RC5.h Этот файл никуда кроме projectname.h и RC5.c не инклюдится.
Короче, я так понял. Переменные я вс-таки должен объявлять ("unsigned char a;") именно в соответствующем сишнике (RC5.c). Тогда те из переменных, которые я хочу использовать другими модулями (файлами) проги, я должен дополнительно описать ("extern unsigned char a;") в h-файле. Те, которые сугубо личные и юзаются только внутри библиотеки - соответственно не описываю. Так?
И соответственно у меня есть файл main.c и projectname.h к нему. В этом h все общие переменные, инклюды и дефайны.
Защита от двойного включения во всех h-файлах естественно написана.YS писал(а):Если файл, в котором она объявлена, включается в две единицы компиляции - то считайте, что она объявлена два раза. Видимо, у вас так и есть.
Специально сделал поиск по всем файлам - запись вида "unsigned char a;" есть только в файле RC5.h Этот файл никуда кроме projectname.h и RC5.c не инклюдится.
Короче, я так понял. Переменные я вс-таки должен объявлять ("unsigned char a;") именно в соответствующем сишнике (RC5.c). Тогда те из переменных, которые я хочу использовать другими модулями (файлами) проги, я должен дополнительно описать ("extern unsigned char a;") в h-файле. Те, которые сугубо личные и юзаются только внутри библиотеки - соответственно не описываю. Так?
Только весь прикол в том, что компилятор компилит сишники по отдельности и инлайнить на этом этапе поздно. А линкер уже ничего сделать не может. Короче, 1 чувак сказал, что инлайн - только внутри модуля и поэтому описание инлайн-функции вместе с телом в порядке исключения разрешается помещать в h-файл, а не c-файл, чтобы компилятор мог ее подставить. Правильно?ploop писал(а):Тут интересный момент: если инлайн-функция встречается в коде один раз, при включенной оптимизации ничто не мешает компилятору включить её в общую простыню инструкций. Не знаю, как обстоит на самом деле, надо почитать.
Походу...WiseLord писал(а):И этот файл инклюдится сразу двумя c-файлами.
Да вроде трое вам про это повторилиaam писал(а):Короче, я так понял. Переменные я вс-таки должен объявлять ("unsigned char a;") именно в соответствующем сишнике (RC5.c). Тогда те из переменных, которые я хочу использовать другими модулями (файлами) проги, я должен дополнительно описать ("extern unsigned char a;") в h-файле. Те, которые сугубо личные и юзаются только внутри библиотеки - соответственно не описываю. Так?
Вообще тоже практика нехорошая. Модуль не должен использовать (и светить наружу) никакие глобальные переменные. Правильнее делать функции, принимающие и возвращающие значения или указатели на всяческие структуры. А сами эти, структуры например, описаны в h-файле, объявлены в с-файле.
В смысле? Разговор был про то, что вы разбили одну большую функцию на несколько мелких. А если вы ещё их по разным файлам раскидали, то естественно никакой компилятор с линкером не разберётся.aam писал(а):Только весь прикол в том, что компилятор компилит сишники по отдельности и инлайнить на этом этапе поздно.
Модулем я считаю отдельный файл (.с) или группу таких файлов, если модуль сложный.
Где-то в стандарте написано что-то типа такого: An external variable must be defined, exactly once, outside of any function; this sets aside storage for it. The variable must also be declared in each function that wants to access it; this states the type of the variable.
Грубо говоря. У тебя есть модуль module
в module.h написано
extern int blabla;
в module.c
int blabla;
то никакой гарантии что blabla будет виден из других модулей нет. В большинстве компиляторов виден. Но, например в IAR MSP430 это происходит через раз.
Но, если ты в файле другого модуля объявишь int blabla; - это будет та же самая переменная.
Но вообще, использование глобальных переменных (а особенно межмодульных) не приводит ни к чему хорошему, и то что вы увидели лишь вершина айсберга. Особенно если над проектом работает больше одного человека. Рекомендую использовать обёртки get/set для работы с ними. Ежели учесть, что в 80% случаев глобальные переменные менять не надо, то все сводится к get-функции.
А в описанной уважаемыми котами выше ситуации и нет двойного включения.aam писал(а):Защита от двойного включения во всех h-файлах естественно написана.
Вам выше описали как надо делать. Не определяйте вообще в .h переменные. Выше все было написаноaam писал(а):Специально сделал поиск по всем файлам - запись вида "unsigned char a;" есть только в файле RC5.h
Где-то в стандарте написано что-то типа такого: An external variable must be defined, exactly once, outside of any function; this sets aside storage for it. The variable must also be declared in each function that wants to access it; this states the type of the variable.
Грубо говоря. У тебя есть модуль module
в module.h написано
extern int blabla;
в module.c
int blabla;
то никакой гарантии что blabla будет виден из других модулей нет. В большинстве компиляторов виден. Но, например в IAR MSP430 это происходит через раз.
Но, если ты в файле другого модуля объявишь int blabla; - это будет та же самая переменная.
Но вообще, использование глобальных переменных (а особенно межмодульных) не приводит ни к чему хорошему, и то что вы увидели лишь вершина айсберга. Особенно если над проектом работает больше одного человека. Рекомендую использовать обёртки get/set для работы с ними. Ежели учесть, что в 80% случаев глобальные переменные менять не надо, то все сводится к get-функции.
Также рекомендую прочесть http://pragprog.com/book/jgade/test-dri ... embedded-c если англ позвоняет, причем не только уважаемому коту aam 
Позволяет применять подходы ООП к embedded C, ну кроме основной темы TDD, которая тоже очень хороша
http://rutracker.org/forum/viewtopic.php?t=3546969 если ктот запиратить хочет )
Позволяет применять подходы ООП к embedded C, ну кроме основной темы TDD, которая тоже очень хороша
http://rutracker.org/forum/viewtopic.php?t=3546969 если ктот запиратить хочет )
Спасибо, кстати. Тоже не мешает почитать, а то ООП расслабляетBCluster писал(а):причем не только уважаемому коту aam
- Сообщения: 7518
- Зарегистрирован: Вс мар 29, 2009 22:09:05
Тут это не поможет.Защита от двойного включения во всех h-файлах естественно написана.
Пример.
foo.h
Код: Выделить всё
...
uint8_t bar;
...
Код: Выделить всё
#include "foo.h"
void main(void)
{
bar=1;
...
}
Код: Выделить всё
#include "foo.h"
...
bar=0;
...
Разница между теорией и практикой на практике гораздо больше, чем в теории.


