IgorKossak 0 16 мая, 2007 Опубликовано 16 мая, 2007 · Жалоба Вот что получается... в мар файле Мои переменные лежат в коде сегменте NEAR_C Relative segment, address: CODE 00000406 - 00000411 (0xc bytes), align: 0 Segment part 9. Intra module refs: cClassDirector::cClassDirector() ENTRY ADDRESS REF BY ===== ======= ====== cClassDirector::initialVoltValueRange 0000040A cClassDirector::initialCurValueRange 0000040E cClassDirector::initialTestValue 00000406 а в ассемблере берутся из ОЗУ.... ... И что это ИАР сделал, то что я ему написал:) NEAR_C это сегмент данных-констант, лежащий как раз там, где ему указано лежать линкером. А это может быть во внешней ПЗУ/ЕЕПРОМ/ФЛЕШ/и как ни странно ОЗУ. Проверьте настройки командного файла линкера. В любом случае доступ к ней как к памяти данных, а не программы, потому и через Z. (Сергей Борщ @ May 16 2007, 13:59) Такое в С++ делать можно. Раз вы этого не знаете - последуйте своему совету: См картинку раздел 4........ В выделенном Вами разделе речь идёт об интегральных (т. е. целых) и перечислимых типах, но никак не о плавающей точке. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
lamerok 0 17 мая, 2007 Опубликовано 17 мая, 2007 · Жалоба NEAR_C это сегмент данных-констант, лежащий как раз там, где ему указано лежать линкером. А это может быть во внешней ПЗУ/ЕЕПРОМ/ФЛЕШ/и как ни странно ОЗУ. Проверьте настройки командного файла линкера. Хочу чтобы константы лежали во ФЛЕШЕ. Но компилятор сам расположил в КОДЕ сегменте(ФЛЕШЕ), а читает из ОЗУ.. непорядок... Согласен, я могу добиться, чтобы все было во флеше, поставив keyword __flash. Перед объявлением константных членов класса. И компилятор верно прочитает из ФЛЕШ. Код приводить не буду.. но читает из флеш по адресу статических констант членов класса. Могу добится чтобы они были в ОЗУ. Просто убрал в настройках компилятора --string_literals_in_flash и компилятор верно расположил все в ОЗУ и прочитал из ОЗУ. Но не пойму что мешает компилятору заменить все на просто число..???.Зачем нужно выделять под static const память, не важно где(в ОЗУ или флеше)...Для каких целей??? Ведь он позволяет сделать это для nonstatic constant (подставить число). (Что запрещено стандартом (проинициализировать их в декларации класса)) В любом случае доступ к ней как к памяти данных, а не программы, потому и через Z. В выделенном Вами разделе речь идёт об интегральных (т. е. целых) и перечислимых типах, но никак не о плавающей точке. Это многое объясняет... Все верно... получается флоат нельзя инициализировать в объявление класса. Спасибо, в споре рождается истина. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Сергей Борщ 119 17 мая, 2007 Опубликовано 17 мая, 2007 · Жалоба Но компилятор сам расположил в КОДЕ сегменте(ФЛЕШЕ), а читает из ОЗУ.. непорядок..."Вася, ты зачем сломал игрушку?" "А оно САМО" Компилятор САМ ничего не делает. Он лишь тупо выполняет то, о чем вы его попросили. Дискуссия действительно плодотворная - про инициализацию статических константных членов прямо в описании класса я не знал, а теперь еще и понял ее механизм. Ведь он позволяет сделать это для nonstatic constant (подставить число). (Что запрещено стандартом (проинициализировать их в декларации класса))Ну хорошо, попробуйте найти разницу в двух словосочетаниях: "nonstatic constant" и "nonstatic constant member". Nonstatic constant никакого отношения к классам не имеет, в отличие от nonstatic constatnt member. Что ж вы все никак не поймете, что если вы завели в классе нестатический член, то размер класа должен (обязан) увеличиться на размер этого члена (плюс выравнивание), даже если этот член read-only (константный). И лишь только если член статический, то он существует один на все объекты этого класса и поэтому память под него выделяется отдельно в количестве один штука на все объекты этого класса. И если этот статический член - константа, то вы можете ее проинициализировать в объявлении класса. Это гарантирует, что во всех .cpp, в которые вы включите определение этого класса константа будет иметь одно и то же значение. Из этого же следует, что значение этого статического константного члена известно компилятору в момент компиляции каждой единицы компиляции и этот факт дает возможность компилятору (но не обязывает) подставить куда надо значение этого члена не резервируя память. Или же вы только объявляете статический константный член в объявлении класса а определяете и инициализируете его где-то в другом месте (.cpp) и тогда компилятор безусловно выделит под него память, но внутри этого файла с момента когда значение константы ему известно может использовать значение инициализирующей константы не читая перемеенную. А инициализировать статический константный член разными значениями в разных единицах компиляции нельзя, потому что разные функции класса могут находиться в разных единицах компиляции но все должны работать с одинаковым (вплоть до значения констант) объектом. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
IgorKossak 0 17 мая, 2007 Опубликовано 17 мая, 2007 · Жалоба Хочу чтобы константы лежали во ФЛЕШЕ. Но компилятор сам расположил в КОДЕ сегменте(ФЛЕШЕ), а читает из ОЗУ.. непорядок... Ещё раз повторяю, NEAR_C расположен не в КОДЕ сегменте, а в DATA сегменте. Как это обычно заявлено в командном файле -Z(DATA)NEAR_C=_EXT_EPROM_BASE:+_EXT_EPROM_SIZE Это пространство ДАННЫХ и если границы этого сегмента перекрываются с ОЗУ, то и будет он лежать в ОЗУ и константы будут браться оттуда. Примените квалификатор __flash и будет всё во flash, а непосредственно подставить плавающую константу согласно стандарта (Вами же приведённого) нельзя. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
lamerok 0 17 мая, 2007 Опубликовано 17 мая, 2007 · Жалоба Что ж вы все никак не поймете, что если вы завели в классе нестатический член, то размер класа должен (обязан) увеличиться на размер этого члена (плюс выравнивание), даже если этот член read-only (константный). Дак как раз это я почти пойму..... Компилятор (IAR 4.21A)этого не поймет. Побробуйте скомпилить вот это... и проверить размер класса сClassDirector // Class.h class cClass { public: float getInternalVoltRange(void) const { return internalVoltRange; } float getInternalCurRange(void) const { return internalCurRange; } float getInternalTest(void) const { return internalTest; } private: float internalVoltRange; float internalCurRange; float internalTest; const float initialVoltValueRange = 800.0f; // Что за вата??? Почему так можно вообще делать??? const float initialCurValueRange = 0.40f; const float initialTestValue = 0.0f; }; а потом вот это // ClassDirtector.h class cClassDirector { public: float getInternalVoltRange(void) const { return internalVoltRange; } float getInternalCurRange(void) const { return internalCurRange; } float getInternalTest(void) const { return internalTest; } private: float internalVoltRange; float internalCurRange; float internalTest; static const float initialVoltValueRange; static const float initialCurValueRange; static const float initialTestValue; }; Размер класса одинаковый в обоих случаях. И лишь только если член статический, то он существует один на все объекты этого класса и поэтому память под него выделяется отдельно в количестве один штука на все объекты этого класса. И если этот статический член - константа, то вы можете ее проинициализировать в объявлении класса. Согласен, но только, если статический член - константа не floating point. Что выяснилось сегодня :) (Спасибо IgorKossak) Это гарантирует, что во всех .cpp, в которые вы включите определение этого класса константа будет иметь одно и то же значение. Из этого же следует, что значение этого статического константного члена известно компилятору в момент компиляции каждой единицы компиляции и этот факт дает возможность компилятору (но не обязывает) подставить куда надо значение этого члена не резервируя память. Или же вы только объявляете статический константный член в объявлении класса а определяете и инициализируете его где-то в другом месте (.cpp) и тогда компилятор безусловно выделит под него память, но внутри этого файла с момента когда значение константы ему известно может использовать значение инициализирующей константы не читая перемеенную. Хммм... Почти согласен ... проведу еще пару экперементов.... подумаю... А инициализировать статический константный член разными значениями в разных единицах компиляции нельзя, потому что разные функции класса могут находиться в разных единицах компиляции но все должны работать с одинаковым (вплоть до значения констант) объектом. Согласен, компилятор просто не позволяет этого сделать. Пишет что он уже проинициализирован. Ещё раз повторяю, NEAR_C расположен не в КОДЕ сегменте, а в DATA сегменте. Как это обычно заявлено в командном файле Ну специально задал -Z(CODE)NEAR_C=_..X_INTVEC_SIZE-_..X_FLASH_END Чтобы все константы сувались в CODE Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Сергей Борщ 119 17 мая, 2007 Опубликовано 17 мая, 2007 · Жалоба -Z(CODE)NEAR_C=_..X_INTVEC_SIZE-_..X_FLASH_END Чтобы все константы сувались в CODE А теперь вспомните, в каком порядке происходит построение программы: сначала компилятор компилирует файл, и для обращения ко всем переменным без квалификатора __flash использует команды доступа в ОЗУ (LD, LDS, ST, STS). Именно квалификатором __flash вы указываете ему, что переменная( :) ) будет лежать во флеш и ее нужно читать через LPM. Потом объектные файлы линкер "склеивает" в один большой проставляя желаемые вами адреса. А если вы компилятору сказали одно, линкеру-другое, то кто после этого вам злобный Буратина? ;) Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
lamerok 0 20 мая, 2007 Опубликовано 20 мая, 2007 · Жалоба А теперь вспомните, в каком порядке происходит построение программы: сначала компилятор компилирует файл, и для обращения ко всем переменным без квалификатора __flash использует команды доступа в ОЗУ (LD, LDS, ST, STS). Именно квалификатором __flash вы указываете ему, что переменная( :) ) будет лежать во флеш и ее нужно читать через LPM. Проверил на 4.21А - Правда ваша. На 4.12А, о чудо - работает так как я хочу... т.е. подставка числа, не резервирует память под static const член класса. В map файле ни слова про них (initialVoltValueRange и т.д.). Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
lamerok 0 21 мая, 2007 Опубликовано 21 мая, 2007 · Жалоба После кучи экспериментов пришел к выводу: 1. Можно получить код с подстановкой непосредственно числа 2. Но трудно так как: а) Обращение к static const члену должно быть в одном *.cpp файле б) Зависит от кода.... Т.е., например, я обращаюсь к static const члену в конструкторе, в теле конструктора, перед обращение, куча условий. Если эти условия заремить или часть из них, или изменить порядок, то компилятор подставляет число, иначе Подставляется адрес static const члена. в) Если обращаться к static const члену в двух и более *.cpp файлах, то в том файле в котором прошла инициализация члена идет подстановка числа в зависимоти от пункта б), в других тупое чтение с адреса члена. 3. Компилятор всегда располагает static const член в одном из сегментов памяти, либо NEAR_I, либо NEAR_C в зависимости от настроек компилятора. 4. Линкер, если не видит, что компилятор где то еще(кроме как в объявлении) использует ссылку на этот член, не резервируте под него память. 5. Если NEAR_C находится в сегменте CODE, то компилятор об этом не знает и читает с ОЗУ (как была сказано Сергеем) 6 Так лучше не делать :) Можно тупо воспользоваться #define, либо как было сказано, использовать __flash (но тогда будет команда чтения из флеша). Спасибо всем за помощь. Да все это касательно floating point. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться