Easyelectronics.ru

Электроника для всех
Текущее время: 22 янв 2021, 12:14

Часовой пояс: UTC + 5 часов



JLCPCB – Прототипы печатных плат за $2/5шт. два слоя. $5/5шт. четыре слоя
Крупнейший производитель печатных плат и прототипов. Более 600000 клиентов и свыше 10000 заказов в день!
Получите скидку на почтовую отправку при первом заказе в JLCPCB!

Начать новую тему Ответить на тему  [ Сообщений: 41 ]  На страницу Пред.  1, 2
Автор Сообщение
 Заголовок сообщения: Re: c++ списки инициализации
СообщениеДобавлено: 14 ноя 2020, 19:47 
Только пришел

Зарегистрирован: 14 ноя 2020, 07:03
Сообщения: 18
Reflector писал(а):
Для этих двух примеров бинарники абсолютно идентичные!


Я хотело было ответить, что может у нас разные компиляторы, но на данных примерах у меня так же работает.
Но вот когда когда пробуешь провернуть такой трюк на более серьезном/реальном классе то то только хуже делает.
Так что рискну предположить, что в на простой пример компилятору хватает мозгов.
Собственно вот, что у меня такой трюк сделал:

Код:
.text:00031D90 _GLOBAL__sub_I__ZN9ZDMAClass9_multSizeE ; DATA XREF: .data:2000E07C↓o
.text:00031D90                 PUSH    {R3,LR}
.text:00031D92                 LDR     R3, =ZDMA
.text:00031D94                 MOV.W   R2, #0x1F4
.text:00031D98                 MOV     R0, R3
.text:00031D9A                 MOVS    R1, #0
.text:00031D9C                 BL      memset
.text:00031DA0                 MOV.W   R2, #0x190
.text:00031DA4                 MOVS    R1, #0
.text:00031DA6                 BL      memset
.text:00031DAA                 POP.W   {R3,LR}
.text:00031DAE                 ADD.W   R0, R0, #0x190  ; this
.text:00031DB2                 B.W     _ZN7znMutexC2Ev ; znMutex::znMutex(void)
.text:00031DB2 ; End of function _GLOBAL__sub_I__ZN9ZDMAClass9_multSizeE


А вот без такого трюка:
Код:
.text:00031A28 _ZN9ZDMAClassC2Ev                       ; CODE XREF: _GLOBAL__sub_I__ZN9ZDMAClass9_multSizeE+2↓j
.text:00031A28                 PUSH    {R4,LR}
.text:00031A2A                 MOV     R4, R0
.text:00031A2C                 BL      _ZN7znMutexC2Ev ; znMutex::znMutex(void)
.text:00031A30                 MOVS    R2, #0x10
.text:00031A32                 MOVS    R1, #0
.text:00031A34                 ADD.W   R0, R4, #0x50 ; 'P'
.text:00031A38                 BL      memset
.text:00031A3C                 MOVS    R3, #0
.text:00031A3E                 STRB.W  R3, [R4,#0x60]
.text:00031A42                 MOV     R0, R4
.text:00031A44                 POP     {R4,PC}
.text:00031A44 ; End of function ZDMAClass::ZDMAClass(void)


То есть трюк еще хуже сделал.


Вернуться к началу
 Профиль  
 
 Заголовок сообщения: Re: c++ списки инициализации
СообщениеДобавлено: 14 ноя 2020, 20:12 
Старожил

Зарегистрирован: 23 янв 2016, 15:37
Сообщения: 1394
hapr-lera писал(а):
Но вот когда когда пробуешь провернуть такой трюк на более серьезном/реальном классе то то только хуже делает.

Давай такой пример серьезного/реального класса чтоб я мог у себя проверить, вдруг там поля в виде других классов которые к тому-же не POD и т.д...


Вернуться к началу
 Профиль  
 
 Заголовок сообщения: Re: c++ списки инициализации
СообщениеДобавлено: 14 ноя 2020, 20:49 
Только пришел

Зарегистрирован: 14 ноя 2020, 07:03
Сообщения: 18
Reflector писал(а):
Давай такой пример серьезного/реального класса чтоб я мог у себя проверить, вдруг там поля в виде других классов которые к тому-же не POD и т.д...


В общем оказалось дело не в размере, класса и тому подобного

достаточно добавить, что то типа такого:

Цитата:
class Test
{
public:
Test() = default;
uint16_t _listCh = 1;
int arr[100] { 0 };
private:
};

Test gtest;


И в итоге int arr[100] { 0 }; - превращается уже в 400 лишних байт во флеше.


Вернуться к началу
 Профиль  
 
 Заголовок сообщения: Re: c++ списки инициализации
СообщениеДобавлено: 14 ноя 2020, 20:54 
Старожил

Зарегистрирован: 23 янв 2016, 15:37
Сообщения: 1394
hapr-lera писал(а):
И в итоге int arr[100] { 0 }; - превращается уже в 400 лишних байт во флеше.

Правильно, то же самое будет и для обычного глобального массива, потому что он не попадает в секцию .bss(для этого нужно оставить массив без инициализации), а инититься данными из флеша. И еще если из массива только читать, то оптимизатор может выкинуть массив из RAM, оставить только во флеше, потому я для теста использовал "|=".


Вернуться к началу
 Профиль  
 
 Заголовок сообщения: Re: c++ списки инициализации
СообщениеДобавлено: 14 ноя 2020, 23:43 
Только пришел

Зарегистрирован: 14 ноя 2020, 07:03
Сообщения: 18
Reflector писал(а):
hapr-lera писал(а):
И в итоге int arr[100] { 0 }; - превращается уже в 400 лишних байт во флеше.

Правильно, то же самое будет и для обычного глобального массива, потому что он не попадает в секцию .bss(для этого нужно оставить массив без инициализации), а инититься данными из флеша. И еще если из массива только читать, то оптимизатор может выкинуть массив из RAM, оставить только во флеше, потому я для теста использовал "|=".


Вообще-то си ведь раскидает куда надо.


Вернуться к началу
 Профиль  
 
 Заголовок сообщения: Re: c++ списки инициализации
СообщениеДобавлено: 15 ноя 2020, 00:02 
Старожил

Зарегистрирован: 23 янв 2016, 15:37
Сообщения: 1394
hapr-lera писал(а):
Вообще-то си ведь раскидает куда надо.

Быть такого не может, чтобы gcc в режиме С++ такой массив инитил из флеша, а в режиме С просто занулял.
Код:
int arr[100] {0};


Вернуться к началу
 Профиль  
 
 Заголовок сообщения: Re: c++ списки инициализации
СообщениеДобавлено: 15 ноя 2020, 00:13 
Только пришел

Зарегистрирован: 14 ноя 2020, 07:03
Сообщения: 18
Reflector писал(а):
hapr-lera писал(а):
Вообще-то си ведь раскидает куда надо.

Быть такого не может, чтобы gcc в режиме С++ такой массив инитил из флеша, а в режиме С просто занулял.
Код:
int arr[100] {0};

Может походу... Не знаю что регулирует с++
Но вот си:

    If the target supports a BSS section, GCC by default puts variables that are
    initialized to zero into BSS. This can save space in the resulting code.
    This option turns off this behavior because some programs explicitly rely on
    variables going to the data section—e.g., so that the resulting executable can
    find the beginning of that section and/or make assumptions based on that.
    The default is ‘-fzero-initialized-in-bss’.

Другими словами - для си инициализация не чего не стоит - так как есть секция куда он и пихает. А это секция уже специально каждый раз зануляеться во время старта. Вот и от с++ я такое же поведение ожидал...


Вернуться к началу
 Профиль  
 
 Заголовок сообщения: Re: c++ списки инициализации
СообщениеДобавлено: 15 ноя 2020, 00:31 
Старожил

Зарегистрирован: 23 янв 2016, 15:37
Сообщения: 1394
hapr-lera писал(а):
Может походу... Не знаю что регулирует с++
Но вот си:

Где там написано, что это исключительно для С? Документ называется "Using the GNU Compiler Collection" и лично я его использую для C++ :)


Вернуться к началу
 Профиль  
 
 Заголовок сообщения: Re: c++ списки инициализации
СообщениеДобавлено: 15 ноя 2020, 00:44 
Только пришел

Зарегистрирован: 14 ноя 2020, 07:03
Сообщения: 18
Reflector писал(а):
hapr-lera писал(а):
Может походу... Не знаю что регулирует с++
Но вот си:

Где там написано, что это исключительно для С? Документ называется "Using the GNU Compiler Collection" и лично я его использую для C++ :)

Так там написано, что данный флаг по умолчанию используеться)) - другими словами, если его не отключать то он всегда работает. Вот только с++, чхать похоже хотел на него.


Вернуться к началу
 Профиль  
 
 Заголовок сообщения: Re: c++ списки инициализации
СообщениеДобавлено: 15 ноя 2020, 00:56 
Старожил

Зарегистрирован: 23 янв 2016, 15:37
Сообщения: 1394
Долго проверить?


Вернуться к началу
 Профиль  
 
 Заголовок сообщения: Re: c++ списки инициализации
СообщениеДобавлено: 15 ноя 2020, 01:02 
Только пришел

Зарегистрирован: 14 ноя 2020, 07:03
Сообщения: 18
Reflector писал(а):
Долго проверить?

Так я проверял раньше, до того как написал на форуме.
Но для очистки совести еще раз проверил - добавление данного флага не в какую сторону не повлияло.


Вернуться к началу
 Профиль  
 
 Заголовок сообщения: Re: c++ списки инициализации
СообщениеДобавлено: 15 ноя 2020, 02:02 
Старожил

Зарегистрирован: 23 янв 2016, 15:37
Сообщения: 1394
Дело не в языке, проблема с твоим классом в строке:
Код:
uint16_t _listCh = 1;

Конкретно компилятору не нравится единичка, если _listCh присвоить 0, то все содержимое класса будет нулевое и тогда можно использовать memset, а если хоть один байт ненулевой, то будет копирование из флеша. На С будет то же самое, если сделать так:
Код:
int arr[100] = { 1 };

Первый байт ненулевой и уже все...


Вернуться к началу
 Профиль  
 
 Заголовок сообщения: Re: c++ списки инициализации
СообщениеДобавлено: 15 ноя 2020, 02:12 
Старожил

Зарегистрирован: 19 мар 2013, 19:37
Сообщения: 2900
Откуда: Санкт-Петербург
hapr-lera, у вас в примере поле _listCh=1, так что объект в BSS попасть никак не может.
Да и вообще, хотите, чтобы он мог попасть в BSS – убедитесь, что это POD-объект, без виртуальных методов, без конструктора, без инициализации членов (это, считайте, создание конструктора).
И, соответственно, просто объявляйте переменную статической, без инициализации.


Вернуться к началу
 Профиль  
 
 Заголовок сообщения: Re: c++ списки инициализации
СообщениеДобавлено: 15 ноя 2020, 02:23 
Только пришел

Зарегистрирован: 14 ноя 2020, 07:03
Сообщения: 18
Reflector писал(а):
Дело не в языке, проблема с твоим классом в строке:
Код:
uint16_t _listCh = 1;


В этом случае то да.
Код:
int arr[100] = { 10 };


Но в этом случае си во флеш кинет _listCh, в отличии от с++ - и я наделся это изменить в поведении компилятора.
Код:
uint16_t _listCh = 1;
int arr[100] = { 0 };


В этом случае си нечего не будет юзать, а вот с++ использует memset - собственно как по мне это тоже как то странно. Вот я когда задал вопрос думал, есть способ это изменить. Но как вижу единственный вариант - просто там где ноли в с++ не указывать инициализацию.
Код:
uint16_t _listCh = {0};
int arr[100] = { 0 };


Вернуться к началу
 Профиль  
 
 Заголовок сообщения: Re: c++ списки инициализации
СообщениеДобавлено: 15 ноя 2020, 02:32 
Старожил

Зарегистрирован: 23 янв 2016, 15:37
Сообщения: 1394
hapr-lera писал(а):
Но в этом случае си во флеш кинет _listCh, в отличии от с++ - и я наделся это изменить в поведении компилятора.
Код:
uint16_t _listCh = 1;
int arr[100] = { 0 };

Это два разных объекта которые инициализируются независимо и потому не важно что писать в _listCh.


Вернуться к началу
 Профиль  
 
 Заголовок сообщения: Re: c++ списки инициализации
СообщениеДобавлено: 17 ноя 2020, 21:46 
Старожил
Аватара пользователя

Зарегистрирован: 13 янв 2018, 21:36
Сообщения: 1657
hapr-lera писал(а):
Но в этом случае си во флеш кинет _listCh, в отличии от с++ - и я наделся это изменить в поведении компилятора.
Код:
uint16_t _listCh = 1;
int arr[100] = { 0 };
Так вы дайте компилятору одинаковый код.
Код:
// Так на С++
class Test
{
public:
  Test() = default;
  uint16_t _listCh = 1;
  int arr[100] { 0 };
};
Test test;

//Так на Си
struct Test
{
  uint16_t _listCh;
  int arr[100];
};
Test test = { 1, 0 };
И посмотрите куда Си структуру запихнёт. А так вы даёте разный код и хотите одинакового поведения.


Вернуться к началу
 Профиль  
 
Показать сообщения за:  Поле сортировки  
Начать новую тему Ответить на тему  [ Сообщений: 41 ]  На страницу Пред.  1, 2


Часовой пояс: UTC + 5 часов


Кто сейчас на конференции

Сейчас этот форум просматривают: нет зарегистрированных пользователей


Вы не можете начинать темы
Вы не можете отвечать на сообщения
Вы не можете редактировать свои сообщения
Вы не можете удалять свои сообщения
Вы не можете добавлять вложения

Найти:
Перейти:  

Powered by phpBB © 2000, 2002, 2005, 2007 phpBB Group
Русская поддержка phpBB