реклама на сайте
подробности

 
 
> Глюк ИАРа или мой?, Почему ИАР не дает проинициализировать статический атрибут класса
lamerok
сообщение May 14 2007, 06:44
Сообщение #1


Частый гость
**

Группа: Свой
Сообщений: 135
Регистрация: 22-06-04
Из: Челябинск
Пользователь №: 88



Посмотрите плз картинку. Почему ИАР ругается на инициализацию статического члена класса, при этом на инициализацию не статического члена говорит, что атрибут должен быть статическим????.
Эскизы прикрепленных изображений
Прикрепленное изображение
 
Go to the top of the page
 
+Quote Post
2 страниц V   1 2 >  
Start new topic
Ответов (1 - 22)
Сергей Борщ
сообщение May 14 2007, 12:00
Сообщение #2


Гуру
******

Группа: Модераторы
Сообщений: 8 455
Регистрация: 15-05-06
Из: Рига, Латвия
Пользователь №: 17 095



Цитата(lamerok @ May 14 2007, 09:44) *
Посмотрите плз картинку. Почему ИАР ругается на инициализацию статического члена класса, при этом на инициализацию не статического члена говорит, что атрибут должен быть статическим????.
Попробуйте так:
Код
class cClassDir
{

private:
   static tF32 const initVolt;
   tF32 const initTest;
};

// in .cpp:
cClassDir::cClassDir() : initTest(4.0f) {}
tF32 cClassDir::initVolt = 5.0f;
P.S. А виноват, конечно, компилятор smile.gif


--------------------
На любой вопрос даю любой ответ
"Write code that is guaranteed to work, not code that doesn’t seem to break" (C++ FAQ)
Go to the top of the page
 
+Quote Post
IgorKossak
сообщение May 14 2007, 15:26
Сообщение #3


Шаман
******

Группа: Модераторы
Сообщений: 3 064
Регистрация: 30-06-04
Из: Киев, Украина
Пользователь №: 221



Статические члены класса определяются и инициализируются отдельно, т. к. под них выделяется память и единожды, т. к. определение класса может быть помещено в хёдер.
Go to the top of the page
 
+Quote Post
lamerok
сообщение May 15 2007, 02:31
Сообщение #4


Частый гость
**

Группа: Свой
Сообщений: 135
Регистрация: 22-06-04
Из: Челябинск
Пользователь №: 88



Цитата(Сергей Борщ @ May 14 2007, 15:00) *
Попробуйте так:
Код
class cClassDir
{

private:
   static tF32 const initVolt;
   tF32 const initTest;
};

// in .cpp:
cClassDir::cClassDir() : initTest(4.0f) {}
tF32 cClassDir::initVolt = 5.0f;
P.S. А виноват, конечно, компилятор smile.gif


Спасибо, так компилятор съел...
Код
const float cClass::initialVoltValueRange = 800.0f;
const float cClass::initialCurValueRange =  0.5f;
const float cClass::initialTestValue = 8.0f;

cClass::cClass(void)    
{
   internalVoltRange = initialVoltValueRange;
   internalCurRange = initialCurValueRange;
   internalTest = initialTestValue;
}


но вот что получилось в ассемблере....

Код
     66                internalVotlRange = initialVoltValueRange;
   \   000000C4   ....               LDI     R16, LOW(??initialVoltValueRange)
   \   000000C6   ....               LDI     R17, (??initialVoltValueRange) >> 8
   \   000000C8   01F8               MOVW    R31:R30, R17:R16
   \   000000CA   8140               LD      R20, Z
   \   000000CC   8151               LDD     R21, Z+1
   \   000000CE   8162               LDD     R22, Z+2
   \   000000D0   8173               LDD     R23, Z+3
   \   000000D2   01F3               MOVW    R31:R30, R7:R6
   \   000000D4   AF41               STD     Z+57, R20
   \   000000D6   AF52               STD     Z+58, R21
   \   000000D8   AF63               STD     Z+59, R22
   \   000000DA   AF74               STD     Z+60, R23
     67                internalCurRange = initialCurValueRange;
   \   000000DC   01F8               MOVW    R31:R30, R17:R16
   \   000000DE   8144               LDD     R20, Z+4
   \   000000E0   8155               LDD     R21, Z+5
   \   000000E2   8166               LDD     R22, Z+6
   \   000000E4   8177               LDD     R23, Z+7
   \   000000E6   934D               ST      X+, R20
   \   000000E8   935D               ST      X+, R21
   \   000000EA   936D               ST      X+, R22
   \   000000EC   937C               ST      X, R23
   \   000000EE   9713               SBIW    R27:R26, 3
     68                internalTest = initialTestValue;
   \   000000F0   8500               LDD     R16, Z+8
   \   000000F2   8511               LDD     R17, Z+9
   \   000000F4   8522               LDD     R18, Z+10
   \   000000F6   8533               LDD     R19, Z+11
   \   000000F8   01FD               MOVW    R31:R30, R27:R26
   \   000000FA   8304               STD     Z+4, R16
   \   000000FC   8315               STD     Z+5, R17
   \   000000FE   8326               STD     Z+6, R18
   \   00000100   8337               STD     Z+7, R19


Т.е. данные берутся из ОЗУ а нужно из памяти программ.... Опять глюк компилятора????

Кстати из первого моего поста, если не делать атрибут класса статическим и проинициализировать его, то ИАР дает предупреждение, как видно на картинке (говорит, что не стаический член класса не рекумендуется инициализировать, сделайте его статическим). И выдает верный код в ассемблере!!!!!
Т.е подставляет непосредственно число (LDI R16, 0 -> LDI R18, 72 -> LDI R19, 68). См. код

Код
     66                internalVoltRange = initialVoltValueRange;
   \   000000C0   E000               LDI     R16, 0
   \   000000C2   E428               LDI     R18, 72
   \   000000C4   E434               LDI     R19, 68
   \   000000C6   01F2               MOVW    R31:R30, R5:R4
   \   000000C8   AF01               STD     Z+57, R16
   \   000000CA   AF02               STD     Z+58, R16
   \   000000CC   AF23               STD     Z+59, R18
   \   000000CE   AF34               STD     Z+60, R19
     67                internalCurRange = initialCurValueRange;
   \   000000D0   EC0D               LDI     R16, 205
   \   000000D2   EC1C               LDI     R17, 204
   \   000000D4   E33E               LDI     R19, 62
   \   000000D6   01F3               MOVW    R31:R30, R7:R6
   \   000000D8   8300               ST      Z, R16
   \   000000DA   8311               STD     Z+1, R17
   \   000000DC   8312               STD     Z+2, R17
   \   000000DE   8333               STD     Z+3, R19
     68                internalTest = initialTestValue;
   \   000000E0   E000               LDI     R16, 0
   \   000000E2   E010               LDI     R17, 0
   \   000000E4   8304               STD     Z+4, R16
   \   000000E6   8305               STD     Z+5, R16
   \   000000E8   8306               STD     Z+6, R16
   \   000000EA   8307               STD     Z+7, R16

Ничего не понимаю....
Обращаться в ИАР????
Go to the top of the page
 
+Quote Post
dxp
сообщение May 15 2007, 03:15
Сообщение #5


Adept
******

Группа: Свой
Сообщений: 3 469
Регистрация: 6-12-04
Из: Novosibirsk
Пользователь №: 1 343



Цитата(lamerok @ May 15 2007, 09:31) *
Т.е. данные берутся из ОЗУ а нужно из памяти программ.... Опять глюк компилятора????

А с чего он должен во флеши-то появиться? От того, что объявили const? Нет, это не причина - сегмент const на платформе AVR расположен в области ОЗУ и никак он во флешь попасть не может. Именно по этой причине и введено расшинение для AVR в виде ключевого слова __flash.

Цитата(lamerok @ May 15 2007, 09:31) *
Кстати из первого моего поста, если не делать атрибут класса статическим и проинициализировать его, то ИАР дает предупреждение,

Совершенно правильно - нестатические члены-данные класса надо иницилизировать в конструкторе - для этого он и предназначен.

Цитата(lamerok @ May 15 2007, 09:31) *
как видно на картинке (говорит, что не стаический член класса не рекумендуется инициализировать, сделайте его статическим). И выдает верный код в ассемблере!!!!!

Делать те или иниые члены статическими или нестатическими надо не по советам компилятора, а на основе собственного замысла - автор программы-то Вы, Вам и решать, что и как лучше реализовать. А классы, их члены, нестатические и статические - это лишь средства (как и все остальное).

Небольшой хинт: статические члены класса - это по сути обычные глобальные переменные, только помещенные в область видимости класса и если это функции (статические функции-члены), то имеющие доступ к закрытым членам класса. Только и всего. Именно поэтому статические члены-данные надо создавать (выделять под них память) и инициализировать как обычные глобальные переменные (только надо квалифицировать именем класса, т.к. они находятся в его scope (области видимости)). Остальные правила точно такие же, как и с обычными глобальными переменными. Жить такой статический член-данное может совей жизнью - может быть не создано ни одного объекта класса, а этот существует сам по себе. Инициализируется он так же на этапе статической иницализации (когда инициализируются все глобальные объекты не класс типов), которая по Стандарту осуществляется до динамической инициализации (вызова конструкторов объектов), и это обстоятельство может быть использовано - во время вызова конструктора статический член-данное уже гарантировано проициализирован.

Цитата(lamerok @ May 15 2007, 09:31) *
Ничего не понимаю....
Обращаться в ИАР????

IAR тут совершенно не причем, надо просто подучить С++. smile.gif


--------------------
«Отыщи всему начало, и ты многое поймёшь» К. Прутков
Go to the top of the page
 
+Quote Post
lamerok
сообщение May 15 2007, 03:43
Сообщение #6


Частый гость
**

Группа: Свой
Сообщений: 135
Регистрация: 22-06-04
Из: Челябинск
Пользователь №: 88



Цитата(dxp @ May 15 2007, 06:15) *
А с чего он должен во флеши-то появиться? От того, что объявили const? Нет, это не причина - сегмент const на платформе AVR расположен в области ОЗУ и никак он во флешь попасть не может. Именно по этой причине и введено расшинение для AVR в виде ключевого слова __flash.


1. Я не говориил, что static const Должен быть во Флеше. Я говорил, что правильный компилятор, Должен static const параметр в коде просто подменить числом!!!! Число естественно лежит в коде (во флеше) smile.gif
См последний дизамблер с прошлого поста. Он так и сделал, но при этом я не писал, что атрибут static!!!! а просто написал const tF32 internalVoltValueRange = 800.0f

Цитата(dxp @ May 15 2007, 06:15) *
Совершенно правильно - нестатические члены-данные класса надо иницилизировать в конструкторе - для этого он и предназначен.
Делать те или иниые члены статическими или нестатическими надо не по советам компилятора, а на основе собственного замысла - автор программы-то Вы, Вам и решать, что и как лучше реализовать. А классы, их члены, нестатические и статические - это лишь средства (как и все остальное).


Вот нестатический мне не нужен. Но компилятор не воспринимает почему-то статический тип и не хочет его инициировать.
Замысел. Объявляем static const атрибут в классе, инициализируем его и это у нас получается, если по Сишному сказать как бы #define. Т.е компилятор в коде должен подставлять не саму пременную, а только число. Так и просиходит, но только в случае если я static нее ставлю перед const. Вопрос почему????
Код
internalVoltRange = initialVoltValueRange;
   \   000000C0   E000               LDI     R16, 0  //00h 00h 73h 68h = 800.0f
   \   000000C2   E428               LDI     R18, 72
   \   000000C4   E434               LDI     R19, 68


Код
// 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;  // Что за вата??? Почему так можно вообще делать???
//      static const float initialVoltValueRange  = 800.0f;  // А вот так почему нельзя????
      const float initialCurValueRange  = 0.40f;  
//     static const float initialCurValueRange  = 0.40f;  
      const float initialTestValue  = 0.0f;
//    static  const float initialTestValue  = 0.0f;
};

// Class.cpp
...
//const float cClass::initialVoltValueRange = 800.0f;
//const float cClass::initialCurValueRange =  0.5f;
//const float cClass::initialTestValue = 8.0f;

cClass::cClass(void)    
{
     internalVoltRange = initialVoltValueRange;
     internalCurRange = initialCurValueRange;
     internalTest = initialTestValue;
}


Цитата(dxp @ May 15 2007, 06:15) *
Именно поэтому статические члены-данные надо создавать (выделять под них память) и инициализировать как обычные глобальные переменные

Но только не static const. Как таковой переменной не существует, есть некий идентификатор только, который компилятор подменяте конктретным числом.

Цитата(dxp @ May 15 2007, 06:15) *
IAR тут совершенно не причем, надо просто подучить С++. smile.gif


ИАР причем, а C++ изучать - так это всем надо сделать smile.gif
Go to the top of the page
 
+Quote Post
Сергей Борщ
сообщение May 15 2007, 10:27
Сообщение #7


Гуру
******

Группа: Модераторы
Сообщений: 8 455
Регистрация: 15-05-06
Из: Рига, Латвия
Пользователь №: 17 095



Цитата(lamerok @ May 15 2007, 06:43) *
Но только не static const. Как таковой переменной не существует, есть некий идентификатор только, который компилятор подменяте конктретным числом.
Еще раз, по губам: Объявлен (описан тип) статический член класса в объявлении класса, которое обычно в .h и которое через include может быть включено в несколько .cpp - файлов. Определен этот член и проинициализирован (ему присвоено значение) в каком-то из .cpp файлов. Внимание, вопрос: откуда компилятор, компилируя другой .cpp - файл знает, какое значение вы присвоили этому члену?
Цитата(lamerok @ May 15 2007, 06:43) *
ИАР причем
Кто бы сомневался, один lamerok д'Артаньян biggrin.gif


--------------------
На любой вопрос даю любой ответ
"Write code that is guaranteed to work, not code that doesn’t seem to break" (C++ FAQ)
Go to the top of the page
 
+Quote Post
IgorKossak
сообщение May 15 2007, 15:51
Сообщение #8


Шаман
******

Группа: Модераторы
Сообщений: 3 064
Регистрация: 30-06-04
Из: Киев, Украина
Пользователь №: 221



Цитата(Сергей Борщ @ May 15 2007, 17:27) *
Еще раз, по губам: Объявлен (описан тип) статический член класса в объявлении класса, которое обычно в .h и которое через include может быть включено в несколько .cpp - файлов. Определен этот член и проинициализирован (ему присвоено значение) в каком-то из .cpp файлов. Внимание, вопрос: откуда компилятор, компилируя другой .cpp - файл знает, какое значение вы присвоили этому члену?

Это не обязательно знать компилятору. А линкер, при сборке проекта, будет это знать в любом случае.
Go to the top of the page
 
+Quote Post
zltigo
сообщение May 15 2007, 16:32
Сообщение #9


Гуру
******

Группа: Свой
Сообщений: 13 372
Регистрация: 27-11-04
Из: Riga, Latvia
Пользователь №: 1 244



Цитата(IgorKossak @ May 15 2007, 22:51) *
Это не обязательно знать компилятору. А линкер, при сборке проекта, будет это знать в любом случае.

Вот линкер и знает, и настраивает адрес константы в сегменте данных. А у lamerok претензии, что константа не прямо в коде (кодовом серменте) находится. А это компилятор мог-бы сделать, и ему даже сказали, что это константа, но ее значение ему в общем случае неведомо по указанной Сергеем причине.


--------------------
Feci, quod potui, faciant meliora potentes
Go to the top of the page
 
+Quote Post
lamerok
сообщение May 16 2007, 00:11
Сообщение #10


Частый гость
**

Группа: Свой
Сообщений: 135
Регистрация: 22-06-04
Из: Челябинск
Пользователь №: 88



Цитата(Сергей Борщ @ May 15 2007, 17:27) *
Внимание, вопрос: откуда компилятор, компилируя другой .cpp - файл знает, какое значение вы присвоили этому члену?

Логично, если компилер должен в одном *.cpp файле подставить значение которе определено в том *.сpp, а в другом *.cpp которое в том *.cpp. Так как компилер компилт последовательно все *.cpp файлы.

Цитата(Сергей Борщ @ May 15 2007, 17:27) *
Кто бы сомневался, один lamerok д'Артаньян biggrin.gif


Если ИАР не причем,тогда встречный вопрос. ИАР вот такую конструкцию (опять повторюсь):
Код
// 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;
};


// Class.cpp
...
//const float cClassDirector::initialVoltValueRange = 800.0f;
//const float cClassDirector::initialCurValueRange =  0.5f;
//const float cClassDirector::initialTestValue = 8.0f;

cClass::cClass(void)    
{

    internalVoltRange = initialVoltValueRange;
    internalCurRange = initialCurValueRange;
    internalTest = initialTestValue;
}


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

И делает подставку числа:
Код
internalVoltRange = initialVoltValueRange;
   \   000000C0   E000               LDI     R16, 0  //00h 00h 73h 68h = 800.0f
   \   000000C2   E428               LDI     R18, 72
   \   000000C4   E434               LDI     R19, 68


Класс у меня синглтон. Но что будет делать ИАР, если я сделаю класс не синглтон, а создам потом два экземпляра этого класса.
ЧТО будет подставлять ИАР вместо атрибута const tF32 initialVoltValueRange?????? ОН не статик и по сути они различаться у разных объектов.
На сколько я понимаю, ИАР как раз в этом случае должен создавать атрибуты у каждого объекта, которые будут занимать память, т.е. что я получил когда сделал их static ...... . Таким образом ИАР делает все наоборот.
(Кстати инициализировать, не статические атрибуты можно только в консрукторе, но только не для ИАР!!!) А если они конст (но не статик), то ИАР должен следить за тем, чтобы я их не поменял потом, но уж точно не делать подмену на число.

Кстати к вопросу о ИАР багах... Синглетон у меня сделан макросом только из-за того, что вот такая конструкция компилируется в ИАР 4.21А, но убивает симулятор. А в 4.12А убивает компилятор.
Код
//singleton.h
#include <new>    

template <class T>
class cSingleton
{
   public:
      _Pragma("inline=forced")
      inline static T* getInstance(void) { return pInstance; }
   protected:
      static void create(void)
      {
         pInstance = new(nothrow) cSingleton();
      }

      cSingleton(void);
   private:
      cSingleton(const T& other);
      const T& operator=(const T& other);
      static T* pInstance;
};

//singleclass.h
#include "singleton.h"

class cSingleClass : public cSingleton<cSingleClass>
{
  public:
    static void runTest() {};
  private:
    tF32 test;
};

//main.cpp
#include "singleclass.h"

int main()
{
  cSingleClass::runTest();
  return 0;
}


Если убрать new, то все хорошо.
Go to the top of the page
 
+Quote Post
Сергей Борщ
сообщение May 16 2007, 04:31
Сообщение #11


Гуру
******

Группа: Модераторы
Сообщений: 8 455
Регистрация: 15-05-06
Из: Рига, Латвия
Пользователь №: 17 095



Цитата(lamerok @ May 16 2007, 07:11) *
Кажется, компилер должен в одном *.cpp файле подставить значение которе определено в том *.сpp, а в другом *.cpp которое в том *.cpp. Так как компилер компилт последовательно все *.cpp файлы.
Не должен!!! Потому что значение статического члена должно быть определено только в одном cpp-файле. Не путайте константную переменную и константный член. Это константная переменная может в разных файлалх иметь одинаковое имя и разное значение.
Цитата(lamerok @ May 16 2007, 07:11) *
ЧТО будет подставлять ИАР вместо атрибута const tF32 initialVoltValueRange?????? ОН не статик и по сути они различаться у разных объектов.
Раз он отличается у разных объектов, значит это обычный константный член. Раз это обычный член, вы его можете проинициализировать в конструкторе. Раз обычный член - константный, значит конструктор - это единственное место, где вы можете его проинициализировать.

Цитата(lamerok @ May 16 2007, 07:11) *
воспринимает как я и задумал, но только почемуто без static
И делает подставку числа:
Это очень частный случай и работа оптимизатора - инициализация оказалась в этом же .cpp - файле и компилятор использовал этот факт (однажды такое поведение сыграло со мной злую шутку - константой был серийный номер, который перед прошивкой проставлялся непосредственно в hex. Как же было весело, когда функции из одного .cpp файла откликались на правильный номер, а из другого - на неправильный).

Про остальное чуть позже допишу, если никто не опередит.

P.S. Машина - дура (ИАР тоже), это не подвергается сомнению. Но не потому, что не делает то, что вы хотите, а наоборот, потому что вместо этого тупо делает именно то, что вы ему написали. Если то, что вы хотите и то, что вы написали - разные вещи, то при чем здесь ИАР?


--------------------
На любой вопрос даю любой ответ
"Write code that is guaranteed to work, not code that doesn’t seem to break" (C++ FAQ)
Go to the top of the page
 
+Quote Post
lamerok
сообщение May 16 2007, 05:23
Сообщение #12


Частый гость
**

Группа: Свой
Сообщений: 135
Регистрация: 22-06-04
Из: Челябинск
Пользователь №: 88



Цитата(Сергей Борщ @ May 16 2007, 11:31) *
Не должен!!! Потому что значение статического члена должно быть определено только в одном cpp-файле. Не путайте константную переменную и константный член. Это константная переменная может в разных файлалх иметь одинаковое имя и разное значение.

Почему в одном месте???? Стандарт не воспрещает этого...
Проверил на других компиляторах, везде один и тот же результат, подстановка конктретного числа.
Например, на 4.12А лицензионном прокатило...
Может быть опции у компилятора, какие нибудь нужно поставить???? ЧТобы он воспринимал это как надо???

Цитата(Сергей Борщ @ May 16 2007, 11:31) *
Раз он отличается у разных объектов, значит это обычный константный член. Раз это обычный член, вы его можете проинициализировать в конструкторе. Раз обычный член - константный, значит конструктор - это единственное место, где вы можете его проинициализировать.


Полностью согласен, тогда чего же ИАР мне позволил инициализацию (не статика) сделать не в конструкторе??? И заменл все это числом????



Цитата(Сергей Борщ @ May 16 2007, 11:31) *
P.S. Машина - дура (ИАР тоже), это не подвергается сомнению. Но не потому, что не делает то, что вы хотите, а наоборот, потому что вместо этого тупо делает именно то, что вы ему написали. Если то, что вы хотите и то, что вы написали - разные вещи, то при чем здесь ИАР?


Когда я инициализирую константу в хидере класса... не савля статик (Такого делать вообще нельзя) ИАР делает то чтоя задумал сделать со статиком..... ТОгда какого хрена он не делает тоже самое со статиком????

Самое интересное другое... Все это не работает только с флоатом... с интом16, инт8, инт 32 все прекрасно канает на всех компиляторах.

И кстати в любом случае результат действия:
internalVoltRange = initialVoltValueRange;
в internalVoltRange должнен стать 800.0f верно???

А в случае когда статик инициализируется в *.cpp
такого не происхит... так как
Go to the top of the page
 
+Quote Post
Сергей Борщ
сообщение May 16 2007, 06:59
Сообщение #13


Гуру
******

Группа: Модераторы
Сообщений: 8 455
Регистрация: 15-05-06
Из: Рига, Латвия
Пользователь №: 17 095



Цитата(lamerok @ May 16 2007, 12:23) *
Почему в одном месте???? Стандарт не воспрещает этого...
Чтобы не толочь дальше воду в ступе, приведите выдержку из стандарта.
Цитата(lamerok @ May 16 2007, 12:23) *
Когда я инициализирую константу в хидере... не савля статик (Такого делать вообще нельзя)
Такое в С++ делать можно. Раз вы этого не знаете - последуйте своему совету:
Цитата
C++ изучать - так это всем надо сделать
Разберитесь, наконец, чем статический константный член отличается от статической константной переменной.
Для константной переменной найдите в книжке, чем отличаются записи int const A = 2; и extern int const A = 2;, тогда вы поймете почему первую запись можно вставлять в .h а второую только в .cpp
Для константного члена помедитируйте над ключевым словом mutable.


--------------------
На любой вопрос даю любой ответ
"Write code that is guaranteed to work, not code that doesn’t seem to break" (C++ FAQ)
Go to the top of the page
 
+Quote Post
lamerok
сообщение May 16 2007, 07:05
Сообщение #14


Частый гость
**

Группа: Свой
Сообщений: 135
Регистрация: 22-06-04
Из: Челябинск
Пользователь №: 88



Вот что получается... в мар файле Мои переменные лежат в коде сегменте
Код
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


а в ассемблере берутся из ОЗУ....

Код
internalVolt = initialUSLValue;
   \   000000D8   ....               LDI     R30, LOW(??initialVoltValueRange)
   \   000000DA   ....               LDI     R31, (??initialVoltValueRange) >> 8
   \   000000DC   8100               LD      R16, Z
   \   000000DE   8111               LDD     R17, Z+1
   \   000000E0   8122               LDD     R18, Z+2
   \   000000E2   8133               LDD     R19, Z+3
   \   000000E4   01FC               MOVW    R31:R30, R25:R24
   \   000000E6   5AE6               SUBI    R30, 166
   \   000000E8   4FFF               SBCI    R31, 255
   \   000000EA   8300               ST      Z, R16
   \   000000EC   8311               STD     Z+1, R17
   \   000000EE   8322               STD     Z+2, R18
   \   000000F0   8333               STD     Z+3, R19


И что это ИАР сделал, то что я ему написалsmile.gif
Go to the top of the page
 
+Quote Post
lamerok
сообщение May 16 2007, 08:23
Сообщение #15


Частый гость
**

Группа: Свой
Сообщений: 135
Регистрация: 22-06-04
Из: Челябинск
Пользователь №: 88



Цитата(Сергей Борщ @ May 16 2007, 13:59) *
Чтобы не толочь дальше воду в ступе, приведите выдержку из стандарта.

Явно в стандарте не указано что так делать нельзя... нельзя значит можно...

Цитата(Сергей Борщ @ May 16 2007, 13:59) *
Такое в С++ делать можно. Раз вы этого не знаете - последуйте своему совету:

См картинку раздел 4........

Цитата(Сергей Борщ @ May 16 2007, 13:59) *
Внимание, вопрос: откуда компилятор, компилируя другой .cpp - файл знает, какое значение вы присвоили этому члену?

Ну опять в разных файлах можно завадать разные значения const float cClass::initialTestValue = 8.0f; в одном скажем и const float cClass::initialTestValue = 10.0f; в другом, если они объявлены статиком
И... Так как мы в каждом *.cpp файле подключаем один и тот же хидер, то компилятор должен увидеть что initialTestValue это статический член, да еще и константа, и никакой не external - память под него выделяТь не надо!!!!!!.
Эскизы прикрепленных изображений
Прикрепленное изображение
 
Go to the top of the page
 
+Quote Post
IgorKossak
сообщение May 16 2007, 16:54
Сообщение #16


Шаман
******

Группа: Модераторы
Сообщений: 3 064
Регистрация: 30-06-04
Из: Киев, Украина
Пользователь №: 221



Цитата(lamerok @ May 16 2007, 14:05) *
Вот что получается... в мар файле Мои переменные лежат в коде сегменте
Код
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


а в ассемблере берутся из ОЗУ....
...
И что это ИАР сделал, то что я ему написалsmile.gif

NEAR_C это сегмент данных-констант, лежащий как раз там, где ему указано лежать линкером. А это может быть во внешней ПЗУ/ЕЕПРОМ/ФЛЕШ/и как ни странно ОЗУ. Проверьте настройки командного файла линкера.
В любом случае доступ к ней как к памяти данных, а не программы, потому и через Z.

Цитата
(Сергей Борщ @ May 16 2007, 13:59)

Такое в С++ делать можно. Раз вы этого не знаете - последуйте своему совету:

См картинку раздел 4........

В выделенном Вами разделе речь идёт об интегральных (т. е. целых) и перечислимых типах, но никак не о плавающей точке.
Go to the top of the page
 
+Quote Post
lamerok
сообщение May 17 2007, 00:57
Сообщение #17


Частый гость
**

Группа: Свой
Сообщений: 135
Регистрация: 22-06-04
Из: Челябинск
Пользователь №: 88



Цитата(IgorKossak @ May 16 2007, 23:54) *
NEAR_C это сегмент данных-констант, лежащий как раз там, где ему указано лежать линкером. А это может быть во внешней ПЗУ/ЕЕПРОМ/ФЛЕШ/и как ни странно ОЗУ. Проверьте настройки командного файла линкера.

Хочу чтобы константы лежали во ФЛЕШЕ. Но компилятор сам расположил в КОДЕ сегменте(ФЛЕШЕ), а читает из ОЗУ.. непорядок...
Согласен, я могу добиться, чтобы все было во флеше, поставив keyword __flash. Перед объявлением константных членов класса. И компилятор верно прочитает из ФЛЕШ. Код приводить не буду.. но читает из флеш по адресу статических констант членов класса.

Могу добится чтобы они были в ОЗУ. Просто убрал в настройках компилятора --string_literals_in_flash и компилятор верно расположил все в ОЗУ и прочитал из ОЗУ.
Но не пойму что мешает компилятору заменить все на просто число..???.Зачем нужно выделять под static const память, не важно где(в ОЗУ или флеше)...Для каких целей???
Ведь он позволяет сделать это для nonstatic constant (подставить число). (Что запрещено стандартом (проинициализировать их в декларации класса))

Цитата(IgorKossak @ May 16 2007, 23:54) *
В любом случае доступ к ней как к памяти данных, а не программы, потому и через Z.
В выделенном Вами разделе речь идёт об интегральных (т. е. целых) и перечислимых типах, но никак не о плавающей точке.

Это многое объясняет... Все верно... получается флоат нельзя инициализировать в объявление класса.
Спасибо, в споре рождается истина.
Go to the top of the page
 
+Quote Post
Сергей Борщ
сообщение May 17 2007, 03:05
Сообщение #18


Гуру
******

Группа: Модераторы
Сообщений: 8 455
Регистрация: 15-05-06
Из: Рига, Латвия
Пользователь №: 17 095



Цитата(lamerok @ May 17 2007, 07:57) *
Но компилятор сам расположил в КОДЕ сегменте(ФЛЕШЕ), а читает из ОЗУ.. непорядок...
"Вася, ты зачем сломал игрушку?" "А оно САМО"
Компилятор САМ ничего не делает. Он лишь тупо выполняет то, о чем вы его попросили.

Дискуссия действительно плодотворная - про инициализацию статических константных членов прямо в описании класса я не знал, а теперь еще и понял ее механизм.
Цитата(lamerok @ May 17 2007, 07:57) *
Ведь он позволяет сделать это для nonstatic constant (подставить число). (Что запрещено стандартом (проинициализировать их в декларации класса))
Ну хорошо, попробуйте найти разницу в двух словосочетаниях: "nonstatic constant" и "nonstatic constant member". Nonstatic constant никакого отношения к классам не имеет, в отличие от nonstatic constatnt member. Что ж вы все никак не поймете, что если вы завели в классе нестатический член, то размер класа должен (обязан) увеличиться на размер этого члена (плюс выравнивание), даже если этот член read-only (константный).
И лишь только если член статический, то он существует один на все объекты этого класса и поэтому память под него выделяется отдельно в количестве один штука на все объекты этого класса. И если этот статический член - константа, то вы можете ее проинициализировать в объявлении класса. Это гарантирует, что во всех .cpp, в которые вы включите определение этого класса константа будет иметь одно и то же значение. Из этого же следует, что значение этого статического константного члена известно компилятору в момент компиляции каждой единицы компиляции и этот факт дает возможность компилятору (но не обязывает) подставить куда надо значение этого члена не резервируя память. Или же вы только объявляете статический константный член в объявлении класса а определяете и инициализируете его где-то в другом месте (.cpp) и тогда компилятор безусловно выделит под него память, но внутри этого файла с момента когда значение константы ему известно может использовать значение инициализирующей константы не читая перемеенную.
А инициализировать статический константный член разными значениями в разных единицах компиляции нельзя, потому что разные функции класса могут находиться в разных единицах компиляции но все должны работать с одинаковым (вплоть до значения констант) объектом.


--------------------
На любой вопрос даю любой ответ
"Write code that is guaranteed to work, not code that doesn’t seem to break" (C++ FAQ)
Go to the top of the page
 
+Quote Post
IgorKossak
сообщение May 17 2007, 05:13
Сообщение #19


Шаман
******

Группа: Модераторы
Сообщений: 3 064
Регистрация: 30-06-04
Из: Киев, Украина
Пользователь №: 221



Цитата(lamerok @ May 17 2007, 07:57) *
Хочу чтобы константы лежали во ФЛЕШЕ. Но компилятор сам расположил в КОДЕ сегменте(ФЛЕШЕ), а читает из ОЗУ.. непорядок...

Ещё раз повторяю, NEAR_C расположен не в КОДЕ сегменте, а в DATA сегменте. Как это обычно заявлено в командном файле
Код
-Z(DATA)NEAR_C=_EXT_EPROM_BASE:+_EXT_EPROM_SIZE

Это пространство ДАННЫХ и если границы этого сегмента перекрываются с ОЗУ, то и будет он лежать в ОЗУ и константы будут браться оттуда. Примените квалификатор __flash и будет всё во flash, а непосредственно подставить плавающую константу согласно стандарта (Вами же приведённого) нельзя.
Go to the top of the page
 
+Quote Post
lamerok
сообщение May 17 2007, 05:19
Сообщение #20


Частый гость
**

Группа: Свой
Сообщений: 135
Регистрация: 22-06-04
Из: Челябинск
Пользователь №: 88



Цитата(Сергей Борщ @ May 17 2007, 10:05) *
Что ж вы все никак не поймете, что если вы завели в классе нестатический член, то размер класа должен (обязан) увеличиться на размер этого члена (плюс выравнивание), даже если этот член 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;
};


Размер класса одинаковый в обоих случаях.
Цитата(Сергей Борщ @ May 17 2007, 10:05) *
И лишь только если член статический, то он существует один на все объекты этого класса и поэтому память под него выделяется отдельно в количестве один штука на все объекты этого класса. И если этот статический член - константа, то вы можете ее проинициализировать в объявлении класса.

Согласен, но только, если статический член - константа не floating point. Что выяснилось сегодня smile.gif (Спасибо IgorKossak)

Цитата(Сергей Борщ @ May 17 2007, 10:05) *
Это гарантирует, что во всех .cpp, в которые вы включите определение этого класса константа будет иметь одно и то же значение. Из этого же следует, что значение этого статического константного члена известно компилятору в момент компиляции каждой единицы компиляции и этот факт дает возможность компилятору (но не обязывает) подставить куда надо значение этого члена не резервируя память. Или же вы только объявляете статический константный член в объявлении класса а определяете и инициализируете его где-то в другом месте (.cpp) и тогда компилятор безусловно выделит под него память, но внутри этого файла с момента когда значение константы ему известно может использовать значение инициализирующей константы не читая перемеенную.

Хммм... Почти согласен ... проведу еще пару экперементов.... подумаю...

Цитата(Сергей Борщ @ May 17 2007, 10:05) *
А инициализировать статический константный член разными значениями в разных единицах компиляции нельзя, потому что разные функции класса могут находиться в разных единицах компиляции но все должны работать с одинаковым (вплоть до значения констант) объектом.

Согласен, компилятор просто не позволяет этого сделать. Пишет что он уже проинициализирован.


Цитата(IgorKossak @ May 17 2007, 12:13) *
Ещё раз повторяю, NEAR_C расположен не в КОДЕ сегменте, а в DATA сегменте. Как это обычно заявлено в командном файле

Ну специально задал
Код
-Z(CODE)NEAR_C=_..X_INTVEC_SIZE-_..X_FLASH_END

Чтобы все константы сувались в CODE
Go to the top of the page
 
+Quote Post
Сергей Борщ
сообщение May 17 2007, 06:13
Сообщение #21


Гуру
******

Группа: Модераторы
Сообщений: 8 455
Регистрация: 15-05-06
Из: Рига, Латвия
Пользователь №: 17 095



Цитата(lamerok @ May 17 2007, 12:19) *
Код
-Z(CODE)NEAR_C=_..X_INTVEC_SIZE-_..X_FLASH_END

Чтобы все константы сувались в CODE
А теперь вспомните, в каком порядке происходит построение программы: сначала компилятор компилирует файл, и для обращения ко всем переменным без квалификатора __flash использует команды доступа в ОЗУ (LD, LDS, ST, STS). Именно квалификатором __flash вы указываете ему, что переменная( smile.gif ) будет лежать во флеш и ее нужно читать через LPM. Потом объектные файлы линкер "склеивает" в один большой проставляя желаемые вами адреса. А если вы компилятору сказали одно, линкеру-другое, то кто после этого вам злобный Буратина? wink.gif


--------------------
На любой вопрос даю любой ответ
"Write code that is guaranteed to work, not code that doesn’t seem to break" (C++ FAQ)
Go to the top of the page
 
+Quote Post
lamerok
сообщение May 20 2007, 16:03
Сообщение #22


Частый гость
**

Группа: Свой
Сообщений: 135
Регистрация: 22-06-04
Из: Челябинск
Пользователь №: 88



Цитата(Сергей Борщ @ May 17 2007, 09:13) *
А теперь вспомните, в каком порядке происходит построение программы: сначала компилятор компилирует файл, и для обращения ко всем переменным без квалификатора __flash использует команды доступа в ОЗУ (LD, LDS, ST, STS). Именно квалификатором __flash вы указываете ему, что переменная( smile.gif ) будет лежать во флеш и ее нужно читать через LPM.


Проверил на 4.21А - Правда ваша.
На 4.12А, о чудо - работает так как я хочу... т.е. подставка числа, не резервирует память под static const член класса. В map файле ни слова про них (initialVoltValueRange и т.д.).
Go to the top of the page
 
+Quote Post
lamerok
сообщение May 21 2007, 14:24
Сообщение #23


Частый гость
**

Группа: Свой
Сообщений: 135
Регистрация: 22-06-04
Из: Челябинск
Пользователь №: 88



После кучи экспериментов пришел к выводу:
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 Так лучше не делать smile.gif Можно тупо воспользоваться #define, либо как было сказано, использовать __flash (но тогда будет команда чтения из флеша).
Спасибо всем за помощь.
Да все это касательно floating point.
Go to the top of the page
 
+Quote Post

2 страниц V   1 2 >
Reply to this topicStart new topic
1 чел. читают эту тему (гостей: 1, скрытых пользователей: 0)
Пользователей: 0

 


RSS Текстовая версия Сейчас: 21st July 2025 - 18:14
Рейтинг@Mail.ru


Страница сгенерированна за 0.01682 секунд с 7
ELECTRONIX ©2004-2016