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

Несимметрия конечного результата vinavr компилятора

Не понимаю разницы, оба варианта псевдокода приведите, чтобы сравнить.

 

(Добавлено позже)

1) Здесь не могу согласиться с вашим высказыванием, что "эта строка имеет право стоять где угодно в пределах от { до;"

Эта строка не может стоять первой

{

temp_ptr1 = pph

pph = pph + 1 <- эта строка имеет право стоять где угодно в пределах от { до;

temp_ptr2 = pph - 4

temp_var1 = *temp_ptr2

temp_var1 = ~temp_var1

*temp_ptr1 = temp_var1

;

 

2) Для компилятора в таком коде *pph++=~(*(pph-4)); нет ничего неоднозначного. Судите сами. Берется значение по

адресу (pph-4), инвертируется, сохраняется по адресу (pph), затем адрес (pph) увеличивается на 1. Где тут неоднозначность?

Здесь компилятор даже предупреждения не может выставить.

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


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

2 =GM=

А вопрос применения МК с хадварной поддержкой LCD рассматривался???

Ну там... PIC какой... или STM8L ...

Или всё это только "мазохизма ради" ???

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


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

Эта строка не может стоять первой
Да, конечно, первой не может. Это я сгоряча.

Но все остальные положения допустимы. И посмотрите внимательно -- они не равноправны.

 

2) Для компилятора в таком коде *pph++=~(*(pph-4)); нет ничего неоднозначного. Судите сами. Берется значение по

адресу (pph-4), инвертируется, сохраняется по адресу (pph), затем адрес (pph) увеличивается на 1. Где тут неоднозначность?

Здесь компилятор даже предупреждения не может выставить.

Но ведь выставил -- про неопределённый результат.

 

Он имеет право вычислить адрес получателя раньше, чем адрес источника. Для pph[0] = ~pph[4]; разницы в порядке вычислений нет и предупреждения нет.

 

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

 

Вот ещё на ту же тему.

unsigned char a, b;
void foo()
{
        a ^= b ^= a ^= b;
}

axorb.c: In function ‘foo’:
axorb.c:5: warning: operation on ‘a’ may be undefined

Та же причина -- в интервале точек следования есть две записи в а. И их порядок не определен. Даже если для конкретного контроллера и конкретного компилятора во всех «испытаниях» будет получаться одинаковый результат и именно тот, которого Вы ждете. Правильный результат -- частный случай неопределённого. Но без гарантий.

 

Если будет время и не поленюсь -- найду соответствующие места в стандарте (хотя, мне кажется, на этом форуме они уже приводились). Но Вам полезнее будет сделать это самостоятельно.

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


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

2 =GM=

А вопрос применения МК с хадварной поддержкой LCD рассматривался???

Ну там... PIC какой... или STM8L ...Или всё это только "мазохизма ради" ???

Всё началось отсюда, там на основе

сломанного электронного термометра был сделан пробник-минивольтметр.

 

Что касается других МК. На STM32F100 discovery писал программку вывода на ЛСД,

который стоит на плате, вот там просто исплевался! Не знаю, кто придумал такое

аппаратное двухмерное представление сегментов, возможно индусы, тогда я думал о

них гораздо лучше, чем они есть на самом деле, но ХУЖЕ просто невозможно придумать,

это даже не мазохизм, а примерно как ржавой тупой пилой самому пилить зажатые в

тисках гениталии.

 

 

{

temp_ptr1 = pph

pph = pph + 1 <- эта строка имеет право стоять где угодно в пределах от { до;

temp_ptr2 = pph - 4

temp_var1 = *temp_ptr2

temp_var1 = ~temp_var1

*temp_ptr1 = temp_var1

;

Извините, Александр, с ходу не углядел, но третью строку вы неправильно представляете. Должно быть "temp_ptr2 = temp_ptr1-4", а не " temp_ptr2 = pph-4".

 

Кстати, порядок для операции присваивания вполне определённый - справа налево.

 

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


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

Не знаю, кто придумал такое

аппаратное двухмерное представление сегментов, возможно индусы, тогда я думал о

них гораздо лучше

Возможно, они вот так шахматы и придумали... не суть...

Просто чего-то с ужасом подумалось, что следующим шагом будет попытка детерминирования

недетерминированного времени входа в прерывание... в борьбе за полную симметрию... так может всё-таки сразу... хардварно???

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


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

Извините, Александр, с ходу не углядел, но третью строку вы неправильно представляете. Должно быть "temp_ptr2 = temp_ptr1-4", а не " temp_ptr2 = pph-4".
Я всё написал правильно. Именно temp_ptr2 = pph-4.

И именно потому, что это один из допустимых вариантов, компилятор и выдаёт предупреждение udefined operation.

 

Кстати, порядок для операции присваивания вполне определённый - справа налево.
Ага, щас™

unsigned char A;
unsigned char foo()
{
    unsigned char temp;
    temp = A = 3;    // Сначала присвоили A, а потом temp ?
    return temp;
}

foo:    
    ldi r24,lo8(3); таки сначала temp
    sts A,r24     ; потом A
    ret

 

Определён не порядок присавиваний, а порядок вычисления присваивающих выражений.

Как видите, это несколько разные вещи, как и пара высказываний «имя массива есть указатель на его первый элемент» (почти правда, работающая в большинстве случаев, как и «порядок присваиваний», но иногда приводящая к недоумению) и «имя массива автоматически приводится к указателю на его первый элемент во всех случаях кроме...».

 

Благодаря определённому порядку во все переменные заносятся величины, полученные вычислениями справа налево, но порядок занесения величин (между двумя точками следования) неопределён. В корректной программе всё нормально.

В некорректной, как в Вашем случае с указателями или как в той цепочке a ^= b ^= a ^= b; компилятор выдаёт предупреждение, что операции над той или иной переменной неопределены.

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


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

В продолжение темы:

PORTA=PORTB=PORTC=0;

может быть скомпилировано в:

PORTC=0;
PORTB=PORTC;
PORTA=PORTB;

А чтение некоторых регистров из SFR иногда не проходит бесследно...

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


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

но порядок занесения величин (между двумя точками следования) неопределён.
Да, чтобы два раза не вставать...

 

В качестве упреждения разных «фи, какой он этот С, вот в ассемблере всё однозначно» предлагаю любителям PDP-11 сказать, что будет результатом операций

  MOV (R0)+, R0;  как бы p = *p++;
  MOV R0, -(R0);  как бы *--p = p;

и при этом сказать, для какой модели PDP-11/версии микрокода такой результат будет :-)

Я уже точно не помню (оно мне и не нужно было, просто когда-то как казус запомнилось, но потом в понимании сути UB помогло), возможно, какая-то из этих строк одинаково выполнялась на любой PDP-11, но одна из них точно выполнялась по разному.

 

В корректной программе
В стандарте есть такое понятие «well-formed», «корректная» может и не самый лучший перевод, но у меня лучше не вышло.

Ещё там есть слова sequence point (точка следования), assignment expression (присваивающее выражение) и side effect (побочный эффект -- в частности, запись в левый операнд присваивающего выражения является побочным эффектом вычисления присваивающего выражения).

Там всё можно найти.

 

А я, пожалуй, на пару с Сергеем тоже на какое-то время уймусь.

Есть более интересные занятия, чем чтение стандарта вслух.

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


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

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

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

Гость
Ответить в этой теме...

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

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

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

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

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

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