|
|
  |
IAR: вопрос типа "глазам не верю" |
|
|
|
Jan 20 2012, 09:15
|

Профессионал
    
Группа: Свой
Сообщений: 1 143
Регистрация: 30-09-08
Из: Новочеркасск
Пользователь №: 40 581

|
лично я совсем не усматриваю того, что вы.
если выражение справа вычислять отдельно, то в конечном итоге мы получаем сравнение char == char, которое с учетом promotion превращается в int == int, но, т.к. переменная v4 содержит УЖЕ УСЕЧЕННЫЙ результат вычисления, то promotion заключается в "приписывании" в старший байт 0 - делается это для обоих переменных и никак не меняет результата. в то время как в первом случае promotion делается так же для обоих сторон выражения, но при этом слева к переменной приписывается 0 в старший байт, а справа - старший байт ВЫЧИСЛЯЕТСЯ. promotion делается независимо от оператора, просто результатом оперции присваивания являтся значение переменной, которая получает значение, и этот результат просто никому не нужен (в данном примере).
--------------------
Я бы взял частями... но мне надо сразу.
|
|
|
|
|
Jan 20 2012, 09:27
|

Нечётный пользователь.
     
Группа: Свой
Сообщений: 2 033
Регистрация: 26-05-05
Из: Бровари, Україна
Пользователь №: 5 417

|
Promotion можно не выполнять (удалять в процессе оптимизации) только тогда, когда observable behavior не изменяется. Т.е. если результат у «абстрактной машины», которая медленно и печально делает все строго по стандарту, и у реального кода не отличается. В случае присваивания c3 = c1 + c2; результат (содержимое c3, которое будет из него прочитано следующими операторами) с promotion и без оного не отличается, это известно заранее, поэтому можно и не делать. В случае if ( а тут вычисления ) — не так. Поэтом делать обязательно. Ну и на закуску — этот пример на codepad (там можно набирать любой код, жать кнопку submit и смотреть результат компиляции и выполнения) avr-gcc иногда страдает недовыбрасыванием promotion при оптимизации. Как я недавно где-то писал — пусть лучше так, чем он мне что-то не пос тандарту сделает, а я буду сидеть и думать в чём дело. Цитата(ARV @ Jan 20 2012, 11:15)  если выражение справа вычислять отдельно, то ... в то время как в первом случае promotion делается так же для обоих сторон выражения, но при этом слева к переменной приписывается 0 в старший байт, а справа - старший байт ВЫЧИСЛЯЕТСЯ. Именно так. На мой взгляд, IAR перестарался с оптимизацией. Так таки всё нормально? Это кто-то где-то недоразобравшись бочку покатил?
--------------------
Ну, я пошёл… Если что – звоните…
|
|
|
|
|
Jan 20 2012, 09:29
|

Профессионал
    
Группа: Свой
Сообщений: 1 143
Регистрация: 30-09-08
Из: Новочеркасск
Пользователь №: 40 581

|
Цитата(ReAl @ Jan 20 2012, 13:17)  Ну и на закуску — этот пример на codepad (там можно набирать любой код, жать кнопку submit и смотреть результат компиляции и выполнения) а доверять такой проверке можно ВСЕГДА? то есть там механизм строко по стандарту делает просчет? кстати, ReAl, если не затруднит, еще один вопрос по стандарту... что стандарт говорит по поводу порядка вычисления выражения? имеем выражение вида A # B # C # D, где A,B,C и D - любые допустимые выражения, а # - любые допустимые операции/операторы с одинаковым приоритетом. что стандарт говорит по поводу порядка вычисления A,B,C и D? или даже чуть иначе: в выражении Код (A # B) == (C # D) определена очередность выражения слева и справа, а так же что будет "первее" вычислено: A или B (С или D) ?
--------------------
Я бы взял частями... но мне надо сразу.
|
|
|
|
|
Jan 20 2012, 09:39
|

Нечётный пользователь.
     
Группа: Свой
Сообщений: 2 033
Регистрация: 26-05-05
Из: Бровари, Україна
Пользователь №: 5 417

|
Цитата(_Ivana @ Jan 20 2012, 11:27)  Насколько я ничего не знаю в стандарте С, то тут или это дыра в стандарте, или пока никто не привел прямую цитату с однозначным толкованием данного случая. Ну так вот и почитайте стандарт самостоятельно. Стандарт существует и независимо от приведения цитаты, так что «или - или» тут не катит. Искать и приводить цитату на этот раз не буду — чем больше я это делаю, тем больше мне говорят, что я выпедриваюсь никому не нужными знаниями. Потрудитесь получить их самостояельно. Цитата(_Ivana @ Jan 20 2012, 11:27)  Если при проверке на равенство вычисляется тип и значение левого выражения, а правое приводится к этому же типу - то будет один результат. Если вычисляются типы и значения обоих выражений и меньший тип расширяется до большего, то другой. Если они сразу приводятся к int, то может быть ещё моменты. Ну так вот и найдите в стандарте это место. Аглицкое слово promotion уже подсказали, осталось поиск по тексту произвести самостоятельно. В вычислениях приводится к самому «старшему» из принимающих участие типов. Достатончо простой логики. Иначе в Код unsignd long total; unsigned char value; total = total + value; total никода не превысит 255. В вычислениях типы меньше int — приводится к int. Это уже специфика С. Цитата(_Ivana @ Jan 20 2012, 11:27)  Кстати, глупый вопрос - а если поменять местами и написать if ((v2 + v3) == v1) результат не поменяется ни в каком компиляторе? Если поменяется — то это вообще п’яный какой-то компилятор. Цитата(_Ivana @ Jan 20 2012, 11:27)  И ещё один - с превышением разрядности при сравнении суммы переменных типа int такой дырки в стандарте нет? Тут ВООБЩЕ ДЫРКИ НЕТ.
--------------------
Ну, я пошёл… Если что – звоните…
|
|
|
|
|
Jan 20 2012, 09:40
|

Йа моск ;)
     
Группа: Модераторы
Сообщений: 4 345
Регистрация: 7-07-05
Из: Kharkiv-city
Пользователь №: 6 610

|
QUOTE наткнулся на тему на другом форуме - говорят, таки да... А проверить религия не позволила? CODE /////////////////////////////////////////////////////////////////////////////// // / // IAR C/C++ Compiler V5.50.0.50277/W32 for Atmel AVR 20/Jan/2012 11:40:15 / // Copyright © 1996-2010 IAR Systems AB. / // / // Source file = E:\AVR\TestVolatile\main.c / // Command line = E:\AVR\TestVolatile\main.c --cpu=m128 -ms -o / // E:\AVR\TestVolatile\Release\Obj\ -D NDEBUG -lCN / // E:\AVR\TestVolatile\Release\List\ -lB / // E:\AVR\TestVolatile\Release\List\ -y / // --initializers_in_flash -s9 --no_clustering -e -I / // D:\EWAVR-5501\avr\INC\ -I D:\EWAVR-5501\avr\INC\DLIB\ / // --eeprom_size 4096 --dlib_config / // D:\EWAVR-5501\avr\LIB\DLIB\dlAVR-3s-ec_mul-n.h / // List file = E:\AVR\TestVolatile\Release\List\main.s90 / // / // / ///////////////////////////////////////////////////////////////////////////////
....
// 41 void foo(void) foo: // 42 { // 43 if (v1 == (v2+v3)) LDS R20, v1 LDI R21, 0 LDS R18, v2 LDI R19, 0 LDS R16, v3 ADD R18, R16 ADC R19, R21 CP R20, R18 CPC R21, R19 BRNE ??foo_0 // 44 PORTB = 0; OUT 0x18, R21 RET // 45 else // 46 PORTB = 1; ??foo_0: LDI R16, 1 OUT 0x18, R16 // 47 } RET
Integer Promotion в наличии, никаких отклонений.
--------------------
"Практика выше (теоретического) познания, ибо она имеет не только достоинство всеобщности, но и непосредственной действительности." - В.И. Ленин
|
|
|
|
|
Jan 20 2012, 09:41
|

Любитель
    
Группа: Свой
Сообщений: 1 864
Регистрация: 20-08-06
Из: Тольятти
Пользователь №: 19 695

|
Прогнал этот код в IAR 6.30.4 для ARM: Код volatile unsigned char v1 = 1; volatile unsigned char v2 = 255; volatile unsigned char v3 = 2;
int result; if (v1 == (v2+v3)) result = 0; else result = 1; результат - result = 1; Сравнение производится в интах: Код \ 00000044 0xF89D 0x0002 LDRB R0,[SP, #+2] \ 00000048 0xF89D 0x1001 LDRB R1,[SP, #+1] \ 0000004C 0xF89D 0x2000 LDRB R2,[SP, #+0] \ 00000050 0x1851 ADDS R1,R2,R1 \ 00000052 0x4288 CMP R0,R1 \ 00000054 0xBF0C ITE EQ \ 00000056 0x2100 MOVEQ R1,#+0 \ 00000058 0x2101 MOVNE R1,#+1 Всё нормально у ИАРа со стандартами. А вот оптимизатор слабенький и всё ещё не дотягивает до оного в Кейле
|
|
|
|
|
Jan 20 2012, 09:44
|

Йа моск ;)
     
Группа: Модераторы
Сообщений: 4 345
Регистрация: 7-07-05
Из: Kharkiv-city
Пользователь №: 6 610

|
QUOTE Прогнал этот код в IAR 6.30.4 для ARM: Ну вообще-то речь об AVR, если уж быть до конца корректным. QUOTE А вот оптимизатор слабенький и всё ещё не дотягивает до оного в Кейле Это Вам кажется.
--------------------
"Практика выше (теоретического) познания, ибо она имеет не только достоинство всеобщности, но и непосредственной действительности." - В.И. Ленин
|
|
|
|
|
Jan 20 2012, 09:48
|

Нечётный пользователь.
     
Группа: Свой
Сообщений: 2 033
Регистрация: 26-05-05
Из: Бровари, Україна
Пользователь №: 5 417

|
Цитата(Палыч @ Jan 20 2012, 11:34)  Может быть Вы и правы, но выглятит как-то "странным" получить разные результаты выполнения двух, следующих друг за другом условных операторов в таком примере Код if (v1 == (v4 = (v2+v3) ) ) { .... } if (v1 == v4 ) { .... } Это третий пример. В нем в операторе == одним из операндов является резальтат «присваивающего выражения» (v4 = (v2+v3) ). Результатом присваивающего выражения A = B по стандарту есть значение выражения B, приведённое к типу A со снятыми квалификаторами. Т.е. запись Код if (v1 == (v4 = (v2+v3) ) ) { .... } с точки зрения результата оператора == абсолютно эквивалентна Код if (v1 == (unsigned char)(v2+v3) ) { .... } и Вы не будете удивлены.
--------------------
Ну, я пошёл… Если что – звоните…
|
|
|
|
|
  |
1 чел. читают эту тему (гостей: 1, скрытых пользователей: 0)
Пользователей: 0
|
|
|