Перейти к содержанию
    

Решил проверить в GCC

    uint16_t i;
    float SigRe[16],*pSigRe;
    pSigRe = SigRe;
    for(i=0; i<16; i++) SigRe[i] = 2.*(i+1);
    for(i=0; i<16; i++) *pSigRe++ = log2f(*pSigRe) * 15.0515;
    for(i=0; i<16; i++) printf("i = %u SigRe[%u] = %f12.5\n",i,i,SigRe[i]);

    for(i=0; i<16; i++) SigRe[i] = 2.*(i+1);
    for(i=0; i<16; i++) SigRe[i] = log2f(SigRe[i]) * 15.0515;
    for(i=0; i<16; i++) printf("i = %u SigRe[%u] = %f12.5\n",i,i,SigRe[i]);

Получил

i = 0 SigRe[0] = 30.10300112.5
i = 1 SigRe[1] = 38.90756212.5
i = 2 SigRe[2] = 45.15449912.5
i = 3 SigRe[3] = 50.00000012.5
i = 4 SigRe[4] = 53.95906412.5
i = 5 SigRe[5] = 57.30640412.5
i = 6 SigRe[6] = 60.20600112.5
i = 7 SigRe[7] = 62.76362612.5
i = 8 SigRe[8] = 65.05149812.5
i = 9 SigRe[9] = 67.12113212.5
i = 10 SigRe[10] = 69.01056712.5
i = 11 SigRe[11] = 70.74866512.5
i = 12 SigRe[12] = 72.35790312.5
i = 13 SigRe[13] = 73.85606412.5
i = 14 SigRe[14] = 75.25750012.5
i = 15 SigRe[15] = -1913.32995612.5
i = 0 SigRe[0] = 15.05150012.5
i = 1 SigRe[1] = 30.10300112.5
i = 2 SigRe[2] = 38.90756212.5
i = 3 SigRe[3] = 45.15449912.5
i = 4 SigRe[4] = 50.00000012.5
i = 5 SigRe[5] = 53.95906412.5
i = 6 SigRe[6] = 57.30640412.5
i = 7 SigRe[7] = 60.20600112.5
i = 8 SigRe[8] = 62.76362612.5
i = 9 SigRe[9] = 65.05149812.5
i = 10 SigRe[10] = 67.12113212.5
i = 11 SigRe[11] = 69.01056712.5
i = 12 SigRe[12] = 70.74866512.5
i = 13 SigRe[13] = 72.35790312.5
i = 14 SigRe[14] = 73.85606412.5
i = 15 SigRe[15] = 75.25750012.5
Hello world!

 

Ругается на

Prj\Hello\main.c:12:32: warning: operation on 'pSigRe' may be undefined [-Wsequence-point]

for(i=0; i<16; i++) *pSigRe++ = log2f(*pSigRe) * 15.0515;

Выходит, что нельзя так.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

А еще правильнее написать авторам cppcheck и задать вопрос напрямую.
Какой вопрос??? Еще на первой странице выяснили: все описано в Стандарте, cppcheck ругается правильно. Но некоторые уже четвертую страницу бубнят "Я переходил дорогу на красный свет и меня не сбили. Нафига в правилах написали, что переходить на красный нельзя?". А некторые еще и переходят на красный, чтобы убедиться.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

**********************************************************************
-O0

000320  490e			  LDR	  r1,|L8.860|
000322  6008			  STR	  r0,[r1,#0] ; SigRe
;;;3771	 pSigRe = SigRe;
000324  460c			  MOV	  r4,r1
;;;3772	 for (uint32_t i = FFT_N; i--; ) {
000326  f44f6680		  MOV	  r6,#0x400
00032a  e00f			  B		|L8.844|
			  |L8.812|
;;;3775	   *pSigRe++ = log2f(*pSigRe) * 15.0515;
00032c  6820			  LDR	  r0,[r4,#0]
00032e  f7fffffe		  BL	   log2f
000332  900b			  STR	  r0,[sp,#0x2c]
000334  f7fffffe		  BL	   __aeabi_f2d
000338  4680			  MOV	  r8,r0
00033a  4a14			  LDR	  r2,|L8.908|
00033c  4b14			  LDR	  r3,|L8.912|
00033e  f7fffffe		  BL	   __aeabi_dmul
000342  e9cd010c		  STRD	 r0,r1,[sp,#0x30]
000346  f7fffffe		  BL	   __aeabi_d2f
00034a  c401			  STM	  r4!,{r0}
			  |L8.844|
00034c  1e30			  SUBS	 r0,r6,#0			 ;3772
00034e  f1a60601		  SUB	  r6,r6,#1			 ;3772
000352  d1eb			  BNE	  |L8.812|
			  |L8.860|
					  DCD	  SigRe
			  |L8.908|
					  DCD	  0x353f7cee
			  |L8.912|
					  DCD	  0x402e1a5e

********************************************************************************
-O0

000320  490e			  LDR	  r1,|L8.860|
000322  6008			  STR	  r0,[r1,#0] ; SigRe
;;;3771	 pSigRe = SigRe;
000324  460c			  MOV	  r4,r1
;;;3772	 for (uint32_t i = FFT_N; i--; ) {
000326  f44f6680		  MOV	  r6,#0x400
00032a  e010			  B		|L8.846|
			  |L8.812|
;;;3775	   *pSigRe = log2f(*pSigRe) * 15.0515;
00032c  6820			  LDR	  r0,[r4,#0]
00032e  f7fffffe		  BL	   log2f
000332  900b			  STR	  r0,[sp,#0x2c]
000334  f7fffffe		  BL	   __aeabi_f2d
000338  4680			  MOV	  r8,r0
00033a  4a14			  LDR	  r2,|L8.908|
00033c  4b14			  LDR	  r3,|L8.912|
00033e  f7fffffe		  BL	   __aeabi_dmul
000342  e9cd010c		  STRD	 r0,r1,[sp,#0x30]
000346  f7fffffe		  BL	   __aeabi_d2f
00034a  6020			  STR	  r0,[r4,#0]
;;;3776   	pSigRe++;
00034c  1d24			  ADDS	 r4,r4,#4
			  |L8.846|
00034e  1e30			  SUBS	 r0,r6,#0			 ;3772
000350  f1a60601		  SUB	  r6,r6,#1			 ;3772
000354  d1ea			  BNE	  |L8.812|
			  |L8.860|
					  DCD	  SigRe
			  |L8.908|
					  DCD	  0x353f7cee
			  |L8.912|
					  DCD	  0x402e1a5e

********************************************************************************
-O3 -Otime

;;;3775	   *pSigRe++ = log2f(*pSigRe) * 15.0515;

000264  f24038ff		  MOV	  r8,#0x3ff			;3722

0002d8  4c0a			  LDR	  r4,|L8.772|
0002da  4d17			  LDR	  r5,|L8.824|
0002dc  4e17			  LDR	  r6,|L8.828|
			  |L8.734|
0002de  6820			  LDR	  r0,[r4,#0]		   ;3775
0002e0  f7fffffe		  BL	   log2f
0002e4  f7fffffe		  BL	   __aeabi_f2d
0002e8  462a			  MOV	  r2,r5				;3775
0002ea  4633			  MOV	  r3,r6				;3775
0002ec  f7fffffe		  BL	   __aeabi_dmul
0002f0  f7fffffe		  BL	   __aeabi_d2f
0002f4  f8440b04		  STR	  r0,[r4],#4		   ;3775
0002f8  f1b80801		  SUBS	 r8,r8,#1			 ;3775
0002fc  d2ef			  BCS	  |L8.734|

			  |L8.772|
					  DCD	  extram
			  |L8.824|
					  DCD	  0x353f7cee
			  |L8.828|
					  DCD	  0x402e1a5e


********************************************************************************
-O3 -Otime

;;;3771	 pSigRe = SigRe;
;;;3772	 for (uint32_t i = FFT_N; i--; ) {
;;;3775	   *pSigRe = log2f(*pSigRe) * 15.0515;
;;;3776   	pSigRe++;
;;;3777	 }
000264  f24038ff		  MOV	  r8,#0x3ff			;3722

0002d8  4c0a			  LDR	  r4,|L8.772|
0002da  4d17			  LDR	  r5,|L8.824|
0002dc  4e17			  LDR	  r6,|L8.828|
			  |L8.734|
0002de  6820			  LDR	  r0,[r4,#0]		   ;3775
0002e0  f7fffffe		  BL	   log2f
0002e4  f7fffffe		  BL	   __aeabi_f2d
0002e8  462a			  MOV	  r2,r5				;3775
0002ea  4633			  MOV	  r3,r6				;3775
0002ec  f7fffffe		  BL	   __aeabi_dmul
0002f0  f7fffffe		  BL	   __aeabi_d2f
0002f4  f8440b04		  STR	  r0,[r4],#4		   ;3775
0002f8  f1b80801		  SUBS	 r8,r8,#1			 ;3775
0002fc  d2ef			  BCS	  |L8.734|

			  |L8.772|
					  DCD	  extram
			  |L8.824|
					  DCD	  0x353f7cee
			  |L8.828|
					  DCD	  0x402e1a5e

 

В общем, для Keil нет разницы. Как нет и никакого преимущества писать сразу *SigRe++ = ...

Учту замечание CppCheck. Но, чтобы снизошло озарение и просветление, так нет.

 

***********************************************************************
-O3
;;;3775       *pSigRe++ = log2f(*pSigRe) * 15.0515;

000208  f24035ff          MOV      r5,#0x3ff

000280  4c09              LDR      r4,|L8.680|
000282  4e12              LDR      r6,|L8.716|
000284  4f12              LDR      r7,|L8.720|
                 |L8.646|
000286  6820              LDR      r0,[r4,#0]            ;3775
000288  f7fffffe          BL       log2f
00028c  f7fffffe          BL       __aeabi_f2d
000290  4632              MOV      r2,r6                 ;3775
000292  463b              MOV      r3,r7                 ;3775
000294  f7fffffe          BL       __aeabi_dmul
000298  f7fffffe          BL       __aeabi_d2f
00029c  c401              STM      r4!,{r0}              ;3775
00029e  1e6d              SUBS     r5,r5,#1              ;3775
0002a0  d2f1              BCS      |L8.646|

                 |L8.680|
                         DCD      extram
                 |L8.716|
                         DCD      0x353f7cee
                 |L8.720|
                         DCD      0x402e1a5e

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Привел код. Скомпилировал на C++ Builder 2010 и в DevC++.

Думаю, пояснения не нужны :laughing:

image.png

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Усё, таперича проникся. Просвещен. Спасибо всем неравнодушным!

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Я думаю, если ассемблер данного конкретного контроллера поддерживает постинкремент указателей, и компилятор использует это свойство, то результат будет всегда один.

Нет, это не так. Это только означает что в данном конкретном случае оптимизатору выгоднее было использовать такой набор команд.

Если вдруг окажется, что эта команда находится в цикле со множеством постинкрементных адресаций в пределах одной итерации цикла:

p = &array[0];
do {
i0 = *p++;
...
i1 = *p++;
...
i2 = *p++;
...
i3 = *p++;
} while ();

то оптимизирующий компилятор сделает:

p = &array[0] - 4;
do {
LDR R1, [R0, #16]!
...
LDR R2, [R0, #4]
...
LDR R3, [R0, #8]
...
LDR R4, [R0, #12]
} while ();

потому что все эти команды внутри цикла в сумме по размеру будут == 4+2+2+2 байт - это меньше, чем:

do {
LDR R1, [R0], #4
...
LDR R2, [R0], #4
...
LDR R3, [R0], #4
...
LDR R4, [R0], #4
} while ();

итого == 4+4+4+4 байт.

В таких случаях выгоднее (в системе команд Cortex-M) сделать один раз приращение указателя в теле цикла, чем в каждой точке *p++.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Зависит от типа оптимизации. Пусть хоть весь цикл развернет в линейный код, лишь бы делал, что задумано.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Удивляет что половина вроде как "опытных" "своих" не знают причин почему так получается.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Удивляет что половина вроде как "опытных" "своих" не знают причин почему так получается.

Для этого и существует форум, ИМХО, для обмена опытом и т.д. Между прочим, такие вещи в книгах особо и не описываются, поэтому даже грамотные специалисты могут и не знать не помнить каких-то подводных камней...

Отдельное спасибо jcxz за пример оптимизирующего решения. Я же все никак до ассемблера кортексов не доберусь...

Изменено пользователем Arlleex

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Удивляет что половина вроде как "опытных" "своих" не знают причин почему так получается.

Просто не пользуются и все такими конструкциями.

template<class... Ts> struct overloaded : Ts... {};

template<class... Ts> overloaded(Ts...) -> overloaded<Ts...>;

  

// usage

overloaded {[](auto arg) {}, [](double arg) {}};

Многие опытные скажут как это работает? Не пользуешься и не знаешь, ничего стыдного

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

ViKo, учтите замечания анализатора. Зачем вам писать компиляторозависимый код? Keil так сделает, IAR - по другому... Портируете код на PC, к примеру, и какой-нибудь майкрософтовский компилятор использует возможность следовать строгому стандарту и сделает ваш код неработоспособным))))

 

 

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Многие опытные скажут как это работает? Не пользуешься и не знаешь, ничего стыдного

Сравнили выстрелы в ногу от постинкремента и приоритета операций, которые с времен чистого С тянутся с новыми фишками 17 версии.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Сравнили выстрелы в ногу от постинкремента и приоритета операций, которые с времен чистого С тянутся с новыми фишками 17 версии.

Ну не пишут опытные программеры конструкции как ТС предложил и все. Зачем?

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

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

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Присоединяйтесь к обсуждению

Вы можете написать сейчас и зарегистрироваться позже. Если у вас есть аккаунт, авторизуйтесь, чтобы опубликовать от имени своего аккаунта.

Гость
К сожалению, ваш контент содержит запрещённые слова. Пожалуйста, отредактируйте контент, чтобы удалить выделенные ниже слова.
Ответить в этой теме...

×   Вставлено с форматированием.   Вставить как обычный текст

  Разрешено использовать не более 75 эмодзи.

×   Ваша ссылка была автоматически встроена.   Отображать как обычную ссылку

×   Ваш предыдущий контент был восстановлен.   Очистить редактор

×   Вы не можете вставлять изображения напрямую. Загружайте или вставляйте изображения по ссылке.

×
×
  • Создать...