Страница 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
:evil: бред! зачем объявлять указатель на массив 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++);
Однако всё строго по стандарту.