Страница 143 из 386
Re: Вопросы по С/С++ (СИ)
Добавлено: Пн мар 18, 2013 15:02:02
unalex
vitalik_1984 писал(а):по мне так вот это вообще лишнее
задача была помигать светодиодами, если вы считаете что в данной ситуации несколько тиков процессора важнее универсальности, то
vitalik_1984 писал(а):просто вспоминается мысль о говнокоде
можете считать меня говнокодером, генерирующим абстрактный код и не имеющим возможности его проверить в работе
ЗЫ. для справки - задачи бывают разные, в одной важен размер кода, в другой скорость, так что делать выводы о том использовать свитч или отдельные функции, можно только ознакомившись с конкретным ТЗ
Re: Вопросы по С/С++ (СИ)
Добавлено: Пн мар 18, 2013 23:46:51
shads
Подскажите, что я делаю не так.....
Пытаюсь сравнить 2 значения в памяти, на второе из них уже указывает указатель, делаю так:
Код: Выделить всё
if (*pIrNecData == *(--pIrNecData))
{.....}
Компилятор почемуто начисто вырезает сравнение.....
Re: Вопросы по С/С++ (СИ)
Добавлено: Вт мар 19, 2013 01:35:27
unalex
shads писал(а):Компилятор почемуто начисто вырезает сравнение.....
это называется оптимизация
зачем их сравнивать, если изначално понятно, что они указывают на одинаковые/разные объекты?
Re: Вопросы по С/С++ (СИ)
Добавлено: Вт мар 19, 2013 05:38:10
HHIMERA
shads писал(а):Компилятор почемуто начисто вырезает сравнение.....
Или что-то объявить как volatile... или объявить дополнительную переменную как volatile и часть преобразований вести через неё...
Re: Вопросы по С/С++ (СИ)
Добавлено: Вт мар 19, 2013 05:57:34
Совесть
Один нашел в этой строчке "одинаковые/разные объекты". Второй не разбираясь лепит "volatile". Браво!!!

Re: Вопросы по С/С++ (СИ)
Добавлено: Вт мар 19, 2013 06:30:05
HHIMERA
А третий - только б звездануть...
Давай... присоединяйся к своим братьям-говнокодерам... портянкой на два листа одним светодиодом рулить будешь...

Re: Вопросы по С/С++ (СИ)
Добавлено: Вт мар 19, 2013 06:48:43
Совесть
Ога, и еще писать переносимый код, хаить CV и восхвалять ассемблер. Вроде ничего не забыл из основных тем форума?!
А по делу, желания нет гадать в чем проблема, смотря на одну строчку кода.
Re: Вопросы по С/С++ (СИ)
Добавлено: Вт мар 19, 2013 08:59:55
ibiza11
shads писал(а):Пытаюсь сравнить 2 значения в памяти, на второе из них уже указывает указатель, делаю так:
приведите листинг. компилятор оптимизирует в целом, а не отдельно строчку. Видимых замечаний по этому коду нет.
Re: Вопросы по С/С++ (СИ)
Добавлено: Вт мар 19, 2013 12:38:22
shads
Да хоть листинг, хоть строчку..... как я понял компилятор (пользуюсь AVRStudio4) в подобных случаях чего то не понимает..... толи нескольких указателей в сравнении, толи префиксы ++/-- к указателям, толи еще чего.....
Вот простенький пример (свой код не стал показывать, т.к. сложнее разобраться будет)
Код: Выделить всё
#include <avr/io.h>
char massiv [10];
int main (void)
{
char* pMassiv = massiv;
for (char i=0; i<10; i++)
*pMassiv++ = i;
if (*(--pMassiv) == *(--pMassiv))
PORTB = 0xff;
else
PORTB = 0x00;
while (1){}
}
Сравниваем последние 2 элемента массива, и хотя там у нас разные данные, компиль просто (молча) вырезает сравнение, и выполняет действие PORTB = 0xff, как будто у нас положительный результат сравнения.....
Код: Выделить всё
6: {
+00000024: E6E0 LDI R30,0x60 Load immediate
+00000025: E0F0 LDI R31,0x00 Load immediate
+00000026: E080 LDI R24,0x00 Load immediate
10: *pMassiv++ = i;
+00000027: 9381 ST Z+,R24 Store indirect and postincrement
9: for (char i=0; i<10; i++)
+00000028: 5F8F SUBI R24,0xFF Subtract immediate
+00000029: 308A CPI R24,0x0A Compare with immediate
+0000002A: F7E1 BRNE PC-0x03 Branch if not equal
13: PORTB = 0xff;
+0000002B: EF8F SER R24 Set Register
+0000002C: BB88 OUT 0x18,R24 Out to I/O location
+0000002D: CFFF RJMP PC-0x0000 Relative jump
13: PORTB = 0xff;
+0000002E: 94F8 CLI Global Interrupt Disable
+0000002F: CFFF RJMP PC-0x0000 Relative jump
Re: Вопросы по С/С++ (СИ)
Добавлено: Вт мар 19, 2013 12:48:58
shads
А вот так, работает.....
Но уперто не хочет применять индексный регистр, хотя казалось бы - адрес в нем уже имеется..... так нет же тратит лишний флэш на загрузку обоих байтов командой LDS.....
Код: Выделить всё
#include <avr/io.h>
char massiv [10];
int main (void)
{
char* pMassiv = massiv;
for (char i=0; i<10; i++)
*pMassiv++ = i;
char temp = *(--pMassiv);
if (temp == *(--pMassiv))
PORTB = 0xff;
else
PORTB = 0x00;
while (1){}
}
Re: Вопросы по С/С++ (СИ)
Добавлено: Вт мар 19, 2013 12:55:41
ibiza11
у Вас же другой вопрос был. без двух преддекрементов в одной строчке.
Re: Вопросы по С/С++ (СИ)
Добавлено: Вт мар 19, 2013 13:06:29
shads
ibiza11 писал(а):у Вас же другой вопрос был. без двух преддекрементов в одной строчке.
Это ничего не меняет.....
Код: Выделить всё
#include <avr/io.h>
char massiv [10];
int main (void)
{
char* pMassiv = massiv;
for (char i=0; i<10; i++)
*pMassiv++ = i;
pMassiv = massiv;
if (*pMassiv == *(++pMassiv))
PORTB = 0xff;
else
PORTB = 0x00;
while (1){}
}
результат:
Код: Выделить всё
5: {
+00000024: E6E0 LDI R30,0x60 Load immediate
+00000025: E0F0 LDI R31,0x00 Load immediate
+00000026: E080 LDI R24,0x00 Load immediate
8: *pMassiv++ = i;
+00000027: 9381 ST Z+,R24 Store indirect and postincrement
7: for (char i=0; i<10; i++)
+00000028: 5F8F SUBI R24,0xFF Subtract immediate
+00000029: 308A CPI R24,0x0A Compare with immediate
+0000002A: F7E1 BRNE PC-0x03 Branch if not equal
12: PORTB = 0xff;
+0000002B: EF8F SER R24 Set Register
+0000002C: BB88 OUT 0x18,R24 Out to I/O location
+0000002D: CFFF RJMP PC-0x0000 Relative jump
Re: Вопросы по С/С++ (СИ)
Добавлено: Вт мар 19, 2013 13:13:40
ibiza11
в общем, поскольку в условии if используется одна переменная (указатель) и в составе условия есть математические операции пред/пост декремента/инкремента, то они выполняются до проверки условия.
т.е в случае
Код: Выделить всё
if (*pIrNecData == *(--pIrNecData))
{.....}
сначала происходит преддекремент pIrNecData, а потом уже сравнение двух выражений *(pIrNecData), которые равны.
Аналогично во всех остальных случаях.
Re: Вопросы по С/С++ (СИ)
Добавлено: Вт мар 19, 2013 13:15:44
shads
Корочь химера был прав
HHIMERA писал(а):объявить дополнительную переменную как volatile и часть преобразований вести через неё...
Тока можно и без volatile.
ЗЫ Просто у программиста логика - человеческая, а у компа - машинная.....
ЗЫЗЫ В общем вывод: нельзя в сравнении использовать один указатель больше одного раза..... правильный вывод?
ЗЫЗЫЗЫ Интересно, а почему тогда компилятор ни гугу.... хотябы ругнулся на лишний (недостающий) префикс. Ведь с человеческой точки зрения, все должно произойти именно так как я изначально ожидал..... Наверное упущение программеров создавших компилятор.
Надо еще в 6-ке проверить, как себя вести будет такое построение.....
Re: Вопросы по С/С++ (СИ)
Добавлено: Вт мар 19, 2013 13:28:22
ibiza11
shads писал(а):ЗЫЗЫ В общем вывод: нельзя в сравнении использовать один указатель больше одного раза..... правильный вывод?
Неправильный вывод
вот пример, который будет работать:
Код: Выделить всё
if (*pIrNecData == *(pIrNecData-1))
{.....}
Надо еще в 6-ке проверить, как себя вести будет такое построение.....
Можете не проверять, я проверял в Keil MDK ARM - компилятор интерпретирует Вашу запись аналогично 4ой студии.
Re: Вопросы по С/С++ (СИ)
Добавлено: Вт мар 19, 2013 13:28:55
IM1
shads писал(а):Корочь химера был прав
Ага.
Код: Выделить всё
#include <avr/io.h>
char massiv [10];
volatile char *pMassiv = massiv;
int main (void)
{
for (char i=0; i<10; i++)
*pMassiv++ = i;
if (*(--pMassiv) == *(--pMassiv))
PORTB = 0xff;
else
PORTB = 0x00;
while (1){}
Дизассемблер
Код: Выделить всё
{
for (char i=0; i<10; i++)
00000024 LDI R24,0x00 Load immediate
*pMassiv++ = i;
00000025 LDS R30,0x0060 Load direct from data space
00000027 LDS R31,0x0061 Load direct from data space
00000029 MOVW R26,R30 Copy register pair
0000002A ST X+,R24 Store indirect and postincrement
0000002B STS 0x0061,R27 Store direct to data space
0000002D STS 0x0060,R26 Store direct to data space
for (char i=0; i<10; i++)
0000002F SUBI R24,0xFF Subtract immediate
00000030 CPI R24,0x0A Compare with immediate
00000031 BRNE PC-0x0C Branch if not equal
if (*(--pMassiv) == *(--pMassiv))
00000032 STS 0x0061,R31 Store direct to data space
00000034 STS 0x0060,R30 Store direct to data space
00000036 LDD R25,Z+0 Load indirect with displacement
00000037 SBIW R30,0x01 Subtract immediate from word
00000038 STS 0x0061,R31 Store direct to data space
0000003A STS 0x0060,R30 Store direct to data space
0000003C LDD R24,Z+0 Load indirect with displacement
0000003D CP R25,R24 Compare
0000003E BRNE PC+0x04 Branch if not equal
PORTB = 0xff;
0000003F SER R24 Set Register
00000040 OUT 0x18,R24 Out to I/O location
00000041 RJMP PC+0x0002 Relative jump
PORTB = 0x00;
00000042 OUT 0x18,R1 Out to I/O location
00000043 RJMP PC-0x0000 Relative jump
Re: Вопросы по С/С++ (СИ)
Добавлено: Вт мар 19, 2013 13:33:06
ibiza11

бред! зачем объявлять указатель на массив volatile? он что, у Вас в прерывании меняется?
естественно volatile будет работать в этом случае, поскольку при каждом обращении к указателю будет производиться его преддекремент. Но это равносильно отключению оптимизации этого указателя. Так делать нельзя.
Re: Вопросы по С/С++ (СИ)
Добавлено: Вт мар 19, 2013 13:46:17
IM1
ibiza11 писал(а): бред!
Да нет, оптимизация-сэр! Отработав раз в одном операторе, переменная как правило выбрасывается. Такой вот компилятор.
Re: Вопросы по С/С++ (СИ)
Добавлено: Вт мар 19, 2013 13:49:21
Аlex
Так делать нельзя.
Ну почему же нельзя. volatile как раз и нужен для того, что бы сказать компилятору, что он "не прав" и не должен оптимизировать мысли программиста.
По поводу инкремента. В строке используется же пред-, а не пост-инкремент. Если бы был постинкремент, то оптимизатор можно было бы понять, т.к. условие будет всегда = true. Вообще не понятно, почему он обрезает эту строку, хотя бы инкремент оставил бы.
Re: Вопросы по С/С++ (СИ)
Добавлено: Вт мар 19, 2013 14:04:19
Kavka
Аlex писал(а):По поводу инкремента. В строке используется же пред-, а не пост-инкремент. Если бы был постинкремент, то оптимизатор можно было бы понять, т.к. условие будет всегда = true. Вообще не понятно, почему он обрезает эту строку, хотя бы инкремент оставил бы.
Компилятор это делает потому, что дальше эта переменная нигде не используется. Поставьте вывод её значения в какой-либо порт и компилятор сделает инкремент.
Думаю, что многие будут удивлены результатами этих строк (например для a=5).
x = (++a) + (++a);
x = (a++) + (a++);
Однако всё
строго по стандарту.