реклама на сайте
подробности

 
 
6 страниц V  < 1 2 3 4 5 > »   
Reply to this topicStart new topic
> фича компиляторв, инкремент переменной
Oldring
сообщение May 12 2007, 09:34
Сообщение #31


Гуру
******

Группа: Свой
Сообщений: 3 041
Регистрация: 10-01-05
Из: Москва
Пользователь №: 1 874



Цитата(zltigo @ May 12 2007, 13:26) *
Я приводил.


Не вижу именно разбора выражения. По порядку, что в каком порядке должно вычисляться и почему?


--------------------
Пишите в личку.
Go to the top of the page
 
+Quote Post
zltigo
сообщение May 12 2007, 09:36
Сообщение #32


Гуру
******

Группа: Свой
Сообщений: 13 372
Регистрация: 27-11-04
Из: Riga, Latvia
Пользователь №: 1 244



Цитата(Oldring @ May 12 2007, 12:34) *
Не вижу..

Жаль.


--------------------
Feci, quod potui, faciant meliora potentes
Go to the top of the page
 
+Quote Post
Oldring
сообщение May 12 2007, 09:56
Сообщение #33


Гуру
******

Группа: Свой
Сообщений: 3 041
Регистрация: 10-01-05
Из: Москва
Пользователь №: 1 874



Цитата(zltigo @ May 12 2007, 13:36) *
Жаль.


То есть ссылку на свой пост, про который Вы утверждаете, что там описали формальный разбор выражения, Вы привести не можете?

Цитата(zltigo @ May 12 2007, 13:26) *
Приводили, но не с точки зрения базовых правил а с точки зрения как может быть построена разборка выражения в потрохах компилятора. Что позволяет объяснить, почему появляется неправильный результат и почему стандарт не требует разбирать такую ерунду. Но все это не имеет отношения к пользователю компилятора написавшего дурацкое, сложно разбираемое компилятором (если он за это возьмется!), хреново оптимизируемое и трудно понимаемое человеком, но вполне однозначо трактуемое выражение - "берем одну едиственную переменную, инкрементируем один раз, инкрементируем второй раз, прибавляем к ней ее-же значение.


Нет, грамматические и семантические правила - это часть стандарта языка, а не реализации конкретного компилятора. Я ссылался на грамматические правила и на семантику операций. Выражение x = ++i + ++i; должно быть грамматически разобрано следующим образом (запись дерева - стандартная префиксная)

Код
assign(
    addr( 'x' ),
    sum(
        assign(
            addr( 'i' ),
            add(
                value( addr( 'i' ) ),
                1
            )
        ),
        assign(
            addr( 'i' ),
            add(
                value( addr( 'i' ) ),
                1
            )
        )
    )
)


Как при аккуратном исполнении этого дерева разбора в соответствии с семантическими правилами языка можно получить 14 - не понимаю.

P.S. Если придираться - в этом дереве уже расрыта операция ++i как эквивалентная (i+=1).


--------------------
Пишите в личку.
Go to the top of the page
 
+Quote Post
vetal
сообщение May 12 2007, 10:16
Сообщение #34


Гуру
******

Группа: Модераторы
Сообщений: 2 095
Регистрация: 27-08-04
Из: Россия, СПб
Пользователь №: 553



По моему все очень просто, т.к. код архитектурно зависимый.
Даже считая по дереву:
Код
1. *i=*i+1;[6]
2. *i=*i+1;[7]
3. x=i+i;[14]

С другой стороны, результат в java(как в стековой архитектуре).
Код
1. i=i+1[6]
2. push
3. i=i+1[7]
4. push
5. add[13]

Все прозрачно)))
Go to the top of the page
 
+Quote Post
Oldring
сообщение May 12 2007, 10:21
Сообщение #35


Гуру
******

Группа: Свой
Сообщений: 3 041
Регистрация: 10-01-05
Из: Москва
Пользователь №: 1 874



Цитата(vetal @ May 12 2007, 14:16) *
3. x=i+i;[14][/code]
Все прозрачно)))


Так вот откуда взялась эта третья операция - x = i + i?
Как она получена из дерева разбора выражения?

P.S.

++i эквивалентно i += 1.

Цитата
An assignment expression has the value of the left operand after the assignment, but is not an
lvalue.


--------------------
Пишите в личку.
Go to the top of the page
 
+Quote Post
vetal
сообщение May 12 2007, 10:42
Сообщение #36


Гуру
******

Группа: Модераторы
Сообщений: 2 095
Регистрация: 27-08-04
Из: Россия, СПб
Пользователь №: 553



Цитата
Так вот откуда взялась эта третья операция - x = i + i?
Как она получена из дерева разбора выражения?


В дереве ясно написано x=add {++i,++i}, т.е. сначала выполняются все преинкрементом, а затем выполняется операция сложения. Т.к. операции преинкремента выполняются с одной ячейкой памяти - происходит увеличение ячейки на 2. Операция сложения складывает 2 ячейки памяти с адресом &i, т.е. как и написано в коде. Это вполне справедливо при рассмотрении x86 как машины с памятью, которой она и является)))

Я не могу спрогнозировать результат только на регистровой машине(классической или как при представлении x86 в регистровом эквиваленте), т.к. неопределенность будет зависеть от результата оптимизации. На регистровой машине будут справедливы 2 подхода : -неоптимизированный (по первичному графу) получится как в x86, т.к. сначала выполнятся все "пре" операции и получится результат как в машине с памятью;
-оптимизированный, когда все будет делаться на лету и максимальным использованием регистров код может выглядеть как
Код
ldw   r1, i
add   r1,r1,1
stw   i, r1; можно исключить
mov  r2,r1
add   r2,r2,1
stw    i,r2
add   r3,r1,r2
Go to the top of the page
 
+Quote Post
Oldring
сообщение May 12 2007, 10:52
Сообщение #37


Гуру
******

Группа: Свой
Сообщений: 3 041
Регистрация: 10-01-05
Из: Москва
Пользователь №: 1 874



Цитата(vetal @ May 12 2007, 14:42) *
В дереве ясно написано x=add {++i,++i}, т.е. сначала выполняются все преинкрементом, а затем выполняется операция сложения. Т.к. операции преинкремента выполняются с одной ячейкой памяти - происходит увеличение ячейки на 2. Операция сложения складывает 2 ячейки памяти с адресом &i, т.е. как и написано в коде. Это вполне справедливо при рассмотрении x86 как машины с памятью, которой она и является)))


Не совсем - в дереве ясно написано, что нужно сложить результат первого подвыражения и результат второго подвыражения. Если бы результат подвыражений был lvalue - тогда при вычислении сложения нужно было бы взять у lvalue (неформально - ссылки на объект) значение объекта, и тогда можно было бы прочитать из переменной i результат, отличный от приписанного в i в подвыражении, если бы преобразование lvalue в значение выполнялось после вычисления обоих подвыражений как преобразование типа для операции '+'. Но так как результат вычисления подвыражения lvalue не является - мы не имеем права считывать его обратно из i и обязаны использовать именно то значение, которое было вычислено соответсвующим подвыражением. Одно из подвыражений всегда даст 6, в каком бы порядке ни выполнять операции.

Что происходит в реальных компиляторах - вполне понятно, это не вопрос. Речь шла про "правильность", причем, после закрывания глаз на то, что такое выражение в целом имеет undefined bihavior.


--------------------
Пишите в личку.
Go to the top of the page
 
+Quote Post
vetal
сообщение May 12 2007, 11:11
Сообщение #38


Гуру
******

Группа: Модераторы
Сообщений: 2 095
Регистрация: 27-08-04
Из: Россия, СПб
Пользователь №: 553



Потому и "undefined bihavior", что по моему мнению оператор + складывает 2 ячейки памяти с адресом I, а по вашему он заводит дополнительную переменную. Тут всё и кроется))
Go to the top of the page
 
+Quote Post
zltigo
сообщение May 12 2007, 11:48
Сообщение #39


Гуру
******

Группа: Свой
Сообщений: 13 372
Регистрация: 27-11-04
Из: Riga, Latvia
Пользователь №: 1 244



Цитата(vetal @ May 12 2007, 13:42) *
Это вполне справедливо при рассмотрении x86 как машины с памятью, которой она и является)))

Вся эта бодяга действительно отдана на откуп компилятору в зависимости от платформы. Но что интересно - в результате реального эксперимента все компиляторы для x86 платформы выдали тот самый результат, а под ARM и BF выдали warning - не смогли на штатном механизме обеспечить?
Интересный такой нюанс. Надо будет GNU на не на x86 платформе спытать.


--------------------
Feci, quod potui, faciant meliora potentes
Go to the top of the page
 
+Quote Post
Oldring
сообщение May 12 2007, 12:23
Сообщение #40


Гуру
******

Группа: Свой
Сообщений: 3 041
Регистрация: 10-01-05
Из: Москва
Пользователь №: 1 874



Цитата(vetal @ May 12 2007, 15:11) *
Потому и "undefined bihavior", что по моему мнению оператор + складывает 2 ячейки памяти с адресом I, а по вашему он заводит дополнительную переменную. Тут всё и кроется))


undefined bihavior - потому что часто зависит, например, от порядка вычисления подвыражений, да и для свободы оптимизатора полезно, когда побочные эффекты можно вычислять в произвольном порядке.

Ваше мнение о том, "что оператор + складывает 2 ячейки памяти с адресом i" противоречит утверждению из стандарта, что результат вычисления ++i не есть lvalue. Так что такую интерпретацию принять не могу как "правильную" smile.gif


Цитата(zltigo @ May 12 2007, 15:48) *
Вся эта бодяга действительно отдана на откуп компилятору в зависимости от платформы. Но что интересно - в результате реального эксперимента все компиляторы для x86 платформы выдали тот самый результат, а под ARM и BF выдали warning - не смогли на штатном механизме обеспечить?
Интересный такой нюанс. Надо будет GNU на не на x86 платформе спытать.


arm-elf-gcc версии 4.1.1 выдает 13. cool.gif


--------------------
Пишите в личку.
Go to the top of the page
 
+Quote Post
bus16
сообщение May 12 2007, 12:42
Сообщение #41


Частый гость
**

Группа: Свой
Сообщений: 78
Регистрация: 10-01-07
Пользователь №: 24 270



Посмотрите полученный ассемблерный код на своей машине и всё станет ясно: на ARM без использования стека (ес-но) i=13, на х86 без стека i=14, со стеком i=13.
Вообще беспредметный спор о тёмных сторонах компилляторов, ИМХО.
Go to the top of the page
 
+Quote Post
Oldring
сообщение May 12 2007, 12:46
Сообщение #42


Гуру
******

Группа: Свой
Сообщений: 3 041
Регистрация: 10-01-05
Из: Москва
Пользователь №: 1 874



Цитата(Niko1a$ @ May 12 2007, 16:42) *
Вообще беспредметный спор о тёмных сторонах компилляторов, ИМХО.


Безусловно.
Спор был о том, можно ли считать результат 14 "правильным", называя все остальное - "неправильным".


--------------------
Пишите в личку.
Go to the top of the page
 
+Quote Post
zltigo
сообщение May 12 2007, 13:05
Сообщение #43


Гуру
******

Группа: Свой
Сообщений: 13 372
Регистрация: 27-11-04
Из: Riga, Latvia
Пользователь №: 1 244



Цитата(Oldring @ May 12 2007, 15:23) *
arm-elf-gcc версии 4.1.1 выдает 13. cool.gif

Молча?


--------------------
Feci, quod potui, faciant meliora potentes
Go to the top of the page
 
+Quote Post
vetal
сообщение May 12 2007, 13:09
Сообщение #44


Гуру
******

Группа: Модераторы
Сообщений: 2 095
Регистрация: 27-08-04
Из: Россия, СПб
Пользователь №: 553



nios2-elf-gcc выдает без оптимизации 13, с оптимизацией - 14.
Хотя оптимизированный код выглядит совсем оптимизированным "movi R2, 14" )))
И говорит что так делать нельзя.
Go to the top of the page
 
+Quote Post
Oldring
сообщение May 12 2007, 13:14
Сообщение #45


Гуру
******

Группа: Свой
Сообщений: 3 041
Регистрация: 10-01-05
Из: Москва
Пользователь №: 1 874



Цитата(zltigo @ May 12 2007, 17:05) *
Молча?


По умолчанию - да.

В программе, приведенной ниже, с ключем -Wsequence-point выдается предупреждение "warning: operation on 'i' may be undefined" внутри main(), но не внутри f(). В обоих случаях - 13.

Код
int f( int* p1, int* p2 )
{
    return ++(*p1) + ++(*p2);
}

int main( void )
{
    int i;
    int x1, x2;

    i = 5;
    x1 = ++i + ++i;

    i = 5;
    x2 = f( &i, &i );

    return x2;
}


P.S. С включенной оптимизацией -O3 main своится к возврату 13.


--------------------
Пишите в личку.
Go to the top of the page
 
+Quote Post

6 страниц V  < 1 2 3 4 5 > » 
Reply to this topicStart new topic
4 чел. читают эту тему (гостей: 4, скрытых пользователей: 0)
Пользователей: 0

 


RSS Текстовая версия Сейчас: 24th July 2025 - 21:48
Рейтинг@Mail.ru


Страница сгенерированна за 0.01497 секунд с 7
ELECTRONIX ©2004-2016