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

 
 
2 страниц V   1 2 >  
Reply to this topicStart new topic
> Порядок выполнения операций. Вопрос зантокам!
igorenja
сообщение Nov 11 2009, 06:33
Сообщение #1


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

Группа: Свой
Сообщений: 130
Регистрация: 8-08-08
Из: Новосибирск
Пользователь №: 39 488



Что сделает компилятор увидев такой код:
Код
twi_write_data(0,ptr, data[ptr++]);
Go to the top of the page
 
+Quote Post
HARMHARM
сообщение Nov 11 2009, 06:45
Сообщение #2


читатель даташитов
****

Группа: Свой
Сообщений: 853
Регистрация: 5-11-06
Из: Днепропетровск
Пользователь №: 21 999



Сделает вызов функции. Если найдет соответствующий заголовок.
Объясните свой вопрос. Зантоки и телепаты в отпуске.
Go to the top of the page
 
+Quote Post
igorenja
сообщение Nov 11 2009, 06:49
Сообщение #3


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

Группа: Свой
Сообщений: 130
Регистрация: 8-08-08
Из: Новосибирск
Пользователь №: 39 488



Цитата(HARMHARM @ Nov 11 2009, 12:45) *
Сделает вызов функции. Если найдет соответствующий заголовок.
Объясните свой вопрос. Зантоки и телепаты в отпуске.



Допустип ptr==0, с какими параметрами будет вызвана функция twi_write_data()
Go to the top of the page
 
+Quote Post
Dima_G
сообщение Nov 11 2009, 07:32
Сообщение #4


Местный
***

Группа: Свой
Сообщений: 279
Регистрация: 2-07-08
Из: Новосибирск
Пользователь №: 38 699



Цитата(igorenja @ Nov 11 2009, 10:33) *
Что сделает компилятор увидев такой код:
Код
twi_write_data(0,ptr, data[ptr++]);


Компилятор - скомпилирует. А вот что сделает программа - не определено, тк компиляторозависимо.
Вобщем - бэдстайл
Go to the top of the page
 
+Quote Post
GetSmart
сообщение Nov 11 2009, 07:50
Сообщение #5


.
******

Группа: Участник
Сообщений: 4 005
Регистрация: 3-05-06
Из: Россия
Пользователь №: 16 753



Так писать ИМХО не рекомендуется. А вообще, умный компилятор на такое должен выдавать варнинг, аналогичный как при чтении двух и более волатильных переменных в одной операции.

ЗЫ. На форуме уже была оч похожая тема, но там был прикол с присвоением выражения толи ++n, толи n++.


--------------------
Заблуждаться - Ваше законное право :-)
Go to the top of the page
 
+Quote Post
LessNik
сообщение Nov 11 2009, 07:53
Сообщение #6


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

Группа: Свой
Сообщений: 107
Регистрация: 6-09-06
Из: Москва
Пользователь №: 20 118



Цитата(igorenja @ Nov 11 2009, 09:33) *
Что сделает компилятор увидев такой код:
Код
twi_write_data(0,ptr, data[ptr++]);


У меня выдаёт предупреждение:
Warning[Pa081]: undefined behavior: the order of read and modification of variable "ptr" (or a value reached by some form of indirection through it) is undefined in this statement
Go to the top of the page
 
+Quote Post
igorenja
сообщение Nov 11 2009, 08:02
Сообщение #7


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

Группа: Свой
Сообщений: 130
Регистрация: 8-08-08
Из: Новосибирск
Пользователь №: 39 488



Цитата(LessNik @ Nov 11 2009, 13:53) *
У меня выдаёт предупреждение:
Warning[Pa081]: undefined behavior: the order of read and modification of variable "ptr" (or a value reached by some form of indirection through it) is undefined in this statement



Мой ИАР 4.41 скомпилировал и не выдал ни каких продупреждений.
В итоге работало это вот так:
Код
twi_write_data(0,ptr+1, data[ptr]);

На запись:
Код
twi_write_data(0,ptr++, data[ptr]);

выдаёт предупреждение...
Короче говоря единственно правильный вариант:
Код
twi_write_data(0,ptr, data[ptr]);
ptr++;
Go to the top of the page
 
+Quote Post
_Pasha
сообщение Nov 11 2009, 08:24
Сообщение #8


;
******

Группа: Участник
Сообщений: 5 646
Регистрация: 1-08-07
Пользователь №: 29 509



Цитата
Never rely on argument's order.

Такую татуировку на лоб обычно рекомендуют сделать экспериментаторам.
Go to the top of the page
 
+Quote Post
HARMHARM
сообщение Nov 11 2009, 09:45
Сообщение #9


читатель даташитов
****

Группа: Свой
Сообщений: 853
Регистрация: 5-11-06
Из: Днепропетровск
Пользователь №: 21 999



Цитата(igorenja @ Nov 11 2009, 10:02) *
Короче говоря единственно правильный вариант:
Код
twi_write_data(0,ptr, data[ptr]);
ptr++;

Вообще-то правильнее привыкнуть писать в таких местах ++ptr. Потому что ptr может оказаться сложным типом, при ptr++ может быть создана лишняя копия.
Go to the top of the page
 
+Quote Post
Dima_G
сообщение Nov 11 2009, 12:34
Сообщение #10


Местный
***

Группа: Свой
Сообщений: 279
Регистрация: 2-07-08
Из: Новосибирск
Пользователь №: 38 699



Цитата(HARMHARM @ Nov 11 2009, 13:45) *
Вообще-то правильнее привыкнуть писать в таких местах ++ptr. Потому что ptr может оказаться сложным типом, при ptr++ может быть создана лишняя копия.


Кстати, да.
Из той же серии - полезно писать
for ( ...; ++clVariable_)

Хотя, для части людей сложно поверить в то, что конструкции
for (int i=0; i<10; ++i)
и
for (int i=0; i<10; i++)
Функционально одинаковы, но первая - оптимальнее biggrin.gif
Go to the top of the page
 
+Quote Post
esaulenka
сообщение Nov 11 2009, 12:37
Сообщение #11


Профессионал
*****

Группа: Свой
Сообщений: 1 032
Регистрация: 13-03-08
Из: Маськва
Пользователь №: 35 877



HARMHARM, а можно пример?
Не понимаю...


--------------------
Тут обсуждается творческий порыв, а не соответствие каким-либо стандартам ©
Go to the top of the page
 
+Quote Post
Dima_G
сообщение Nov 11 2009, 12:47
Сообщение #12


Местный
***

Группа: Свой
Сообщений: 279
Регистрация: 2-07-08
Из: Новосибирск
Пользователь №: 38 699



Цитата(esaulenka @ Nov 11 2009, 15:37) *
HARMHARM, а можно пример?
Не понимаю...


надеюсь, ув. HARMHARM не будет против, если я отвечу smile.gif

на пальцах - в случае постинкремента мы
1) изменяем состояние объекта
2) возвращаем предыдущее состояние объекта (вот для сохрения предыдущего состояния как раз и создается копия)

в случае прединкремента мы
1) изменяем состояние объекта
2) возвращаем новое состояние - сохранять старое состояние объекта не требуется
Go to the top of the page
 
+Quote Post
GetSmart
сообщение Nov 11 2009, 12:51
Сообщение #13


.
******

Группа: Участник
Сообщений: 4 005
Регистрация: 3-05-06
Из: Россия
Пользователь №: 16 753



Эта особенность инкремента была актуальна в прошлом веке. Особенно для AVR. Приличные компиляторы (ARM) вне зависимости от варианта инкремента делают одинаковый по размеру и скорости код. Так что не актуально.

Сообщение отредактировал GetSmart - Nov 11 2009, 12:51


--------------------
Заблуждаться - Ваше законное право :-)
Go to the top of the page
 
+Quote Post
Demeny
сообщение Nov 11 2009, 12:55
Сообщение #14


Знающий
****

Группа: Свой
Сообщений: 648
Регистрация: 11-02-06
Из: Санкт-Петербург
Пользователь №: 14 237



Цитата(Dima_G @ Nov 11 2009, 15:34) *
Хотя, для части людей сложно поверить в то, что конструкции
for (int i=0; i<10; ++i)
и
for (int i=0; i<10; i++)
Функционально одинаковы, но первая - оптимальнее biggrin.gif

Бред какой ...
Только что проделал такое с VC 6. Результирующий exe-файл в обоих случаях идентичный (проверено тотал коммандером).


--------------------
Сделано в Китае. Упаковано в России.
Go to the top of the page
 
+Quote Post
esaulenka
сообщение Nov 11 2009, 13:04
Сообщение #15


Профессионал
*****

Группа: Свой
Сообщений: 1 032
Регистрация: 13-03-08
Из: Маськва
Пользователь №: 35 877



Никогда не задумывался...

Но разве ptr++ - это не "сначала использовать переменную ptr, а потом её инкрементировать", а именно "создать копию, инкрементировать один экземпляр, а использовать другой" ?

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


--------------------
Тут обсуждается творческий порыв, а не соответствие каким-либо стандартам ©
Go to the top of the page
 
+Quote Post
Dima_G
сообщение Nov 11 2009, 16:15
Сообщение #16


Местный
***

Группа: Свой
Сообщений: 279
Регистрация: 2-07-08
Из: Новосибирск
Пользователь №: 38 699



Цитата(Demeny @ Nov 11 2009, 16:55) *
Бред какой ...
Только что проделал такое с VC 6. Результирующий exe-файл в обоих случаях идентичный (проверено тотал коммандером).


Потому, что умный компилятор соптимизировал. Но не слишком надейтесь на то, что так будет всегда. Попробуйте проверить с объектом класса с определенным оператором пост и прединкремента
Go to the top of the page
 
+Quote Post
GetSmart
сообщение Nov 11 2009, 16:28
Сообщение #17


.
******

Группа: Участник
Сообщений: 4 005
Регистрация: 3-05-06
Из: Россия
Пользователь №: 16 753



Цитата(Dima_G @ Nov 11 2009, 22:15) *
...Но не слишком надейтесь на то, что так будет всегда...

В 2012-ом все компиляторы дружно разучатся оптимизировать biggrin.gif


--------------------
Заблуждаться - Ваше законное право :-)
Go to the top of the page
 
+Quote Post
Dima_G
сообщение Nov 11 2009, 16:32
Сообщение #18


Местный
***

Группа: Свой
Сообщений: 279
Регистрация: 2-07-08
Из: Новосибирск
Пользователь №: 38 699



Цитата(GetSmart @ Nov 11 2009, 20:28) *
В 2012-ом все компиляторы дружно разучатся оптимизировать biggrin.gif


Имелось в виду - при смене компилятора / платформы / типа данных laughing.gif
Go to the top of the page
 
+Quote Post
zltigo
сообщение Nov 11 2009, 17:41
Сообщение #19


Гуру
******

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



Цитата(Dima_G @ Nov 11 2009, 19:15) *
Потому, что умный компилятор соптимизировал.

А дураки среди компиляторов вымирают, посему пересказывать байки начала 90x не надо. Поздно.
Цитата
Попробуйте проверить с объектом класса с определенным оператором пост и прединкремента

"определенным" это то, что люди называют перегруженным оператором? Это во-первых C++, а во-вторых еще проще для оптимизатора, ибо по стандарту перегрузка оператора заменяется на вызов функции - и никаких фантазий для неправильной оптимизации вообще нет. Нут тебe и железнейшая sequence points еще до кучи.


--------------------
Feci, quod potui, faciant meliora potentes
Go to the top of the page
 
+Quote Post
Dima_G
сообщение Nov 12 2009, 04:31
Сообщение #20


Местный
***

Группа: Свой
Сообщений: 279
Регистрация: 2-07-08
Из: Новосибирск
Пользователь №: 38 699



Цитата(zltigo @ Nov 11 2009, 20:41) *
А дураки среди компиляторов вымирают, посему пересказывать байки начала 90x не надо. Поздно.

"определенным" это то, что люди называют перегруженным оператором? Это во-первых C++, а во-вторых еще проще для оптимизатора, ибо по стандарту перегрузка оператора заменяется на вызов функции - и никаких фантазий для неправильной оптимизации вообще нет. Нут тебe и железнейшая sequence points еще до кучи.


Да, перегруженным.
Вот пример класса. В нем перегружены операторы инкремента

CODE
#include <stdio.h>
#include <time.h>
#include <sys/time.h>

typedef struct timeval TTime;

/////////////////////////////////////////////////
class ClTest
{
public:
int aiBuf_m[1024];

ClTest()
{
aiBuf_m[0] = 0;
}

//Prefix form of increment
ClTest& operator ++()
{
++aiBuf_m[0];
return *this;
}

//Postfix form of increment
ClTest operator ++(int)
{
ClTest clRetValue_ = *this;
++aiBuf_m[0];
return clRetValue_;
}
};

/////////////////////////////////////////////////
unsigned int GetInterval(TTime* psBegin_, TTime* psEnd_)
{
return (psEnd_->tv_usec - psBegin_->tv_usec) + (psEnd_->tv_sec - psBegin_->tv_sec)*1000000;
}

/////////////////////////////////////////////////
int main()
{
TTime sBeginTime_, sEndTime_;
static const unsigned int ITTERATIONS_CNT = 100000;

{
ClTest clTest_;

gettimeofday(&sBeginTime_, NULL);

for (;clTest_.aiBuf_m[0] != ITTERATIONS_CNT; ++clTest_)
continue;

gettimeofday(&sEndTime_, NULL);

printf("Prefix form: time = %u\n", GetInterval(&sBeginTime_, &sEndTime_));
}

{
ClTest clTest_;

gettimeofday(&sBeginTime_, NULL);

for (;clTest_.aiBuf_m[0] != ITTERATIONS_CNT; clTest_++)
continue;

gettimeofday(&sEndTime_, NULL);

printf("Postfix form: time = %u\n", GetInterval(&sBeginTime_, &sEndTime_));
}

return 0;
}


Вот результат его работы (GCC 4.1.2, оптимизация выключена):
Цитата
Prefix form: time = 520
Postfix form: time = 116160


Естественно, при включенной оптимизации эти значения выравниваются. Но не факт, что оптимизация пройдет на более сложных примерах.
Слышал, что люди, хорошо владеющие STL и тп вещами, аккуратнее относятся к пост и пред инкременту.


Собственно, немного изменил пример, и GCC на оптимизации O3 сдулся

Цитата
Prefix form: time = 68
Postfix form: time = 89358


CODE
{
ClTest clTest_;
volatile int i;

gettimeofday(&sBeginTime_, NULL);

for (;clTest_.aiBuf_m[0] != ITTERATIONS_CNT; )
i = (++clTest_).aiBuf_m[0];

gettimeofday(&sEndTime_, NULL);

printf("Prefix form: time = %u\n", GetInterval(&sBeginTime_, &sEndTime_));
}

{
ClTest clTest_;
volatile int i;

gettimeofday(&sBeginTime_, NULL);

for (;clTest_.aiBuf_m[0] != ITTERATIONS_CNT; )
i = (clTest_++).aiBuf_m[0];

gettimeofday(&sEndTime_, NULL);

printf("Postfix form: time = %u\n", GetInterval(&sBeginTime_, &sEndTime_));
}
Причина редактирования: Уменьшение видимого размера цитаты исходника.
Go to the top of the page
 
+Quote Post
GetSmart
сообщение Nov 12 2009, 07:22
Сообщение #21


.
******

Группа: Участник
Сообщений: 4 005
Регистрация: 3-05-06
Из: Россия
Пользователь №: 16 753



Кстати, во FreeRTOS встречаются оба варианта инкремента (без доп. действий) одинакого часто. Автор мечется в сомнении ?! biggrin.gif


--------------------
Заблуждаться - Ваше законное право :-)
Go to the top of the page
 
+Quote Post
Flexz
сообщение Nov 12 2009, 07:56
Сообщение #22


Местный
***

Группа: Свой
Сообщений: 252
Регистрация: 9-10-08
Из: Московская обл.
Пользователь №: 40 797



FreeRTOS просто, видимо, разные люди пишут smile.gif
У Страуструпа, кстати, там где int - постинкремент, а там где итератор - прединкремент
Go to the top of the page
 
+Quote Post
HARMHARM
сообщение Nov 12 2009, 07:58
Сообщение #23


читатель даташитов
****

Группа: Свой
Сообщений: 853
Регистрация: 5-11-06
Из: Днепропетровск
Пользователь №: 21 999



Цитата(Flexz @ Nov 12 2009, 09:56) *
FreeRTOS просто, видимо, разные люди пишут smile.gif

Нет, там один человек. Впрочем, по коду, который долгое время эволюционирует, можно проследить как эволюционирует сам программист smile.gif
Go to the top of the page
 
+Quote Post
Dima_G
сообщение Nov 12 2009, 08:00
Сообщение #24


Местный
***

Группа: Свой
Сообщений: 279
Регистрация: 2-07-08
Из: Новосибирск
Пользователь №: 38 699



Цитата(Flexz @ Nov 12 2009, 11:56) *
У Страуструпа, кстати, там где int - постинкремент, а там где итератор - прединкремент

Со встроенными типами практически всегда это без разницы - компилятор соптимизирует smile.gif (хотя, вдруг выйдет новая интересная платформа + сырой комиплятор rolleyes.gif )

Но лично мне не нравится такой зоопрак из ++i и i++ в программе sad.gif
Поэтому пишу единообразно, используя ++i
Go to the top of the page
 
+Quote Post
_Pasha
сообщение Nov 12 2009, 15:32
Сообщение #25


;
******

Группа: Участник
Сообщений: 5 646
Регистрация: 1-08-07
Пользователь №: 29 509



Цитата(Dima_G @ Nov 12 2009, 12:00) *
Но лично мне не нравится такой зоопрак из ++i и i++ в программе sad.gif
Поэтому пишу единообразно, используя ++i

Ладно-ладно. А volatile-переменные тоже по-умному "додумываются" ? Или все-таки есть разница? wink.gif
Go to the top of the page
 
+Quote Post
Dima_G
сообщение Nov 13 2009, 03:18
Сообщение #26


Местный
***

Группа: Свой
Сообщений: 279
Регистрация: 2-07-08
Из: Новосибирск
Пользователь №: 38 699



Цитата(_Pasha @ Nov 12 2009, 19:32) *
Ладно-ладно. А volatile-переменные тоже по-умному "додумываются" ? Или все-таки есть разница? wink.gif

rolleyes.gif
Чет не пойму, что Вы имеете в виду laughing.gif
Go to the top of the page
 
+Quote Post
defunct
сообщение Nov 13 2009, 13:46
Сообщение #27


кекс
******

Группа: Свой
Сообщений: 3 825
Регистрация: 17-12-05
Из: Киев
Пользователь №: 12 326



Цитата(igorenja @ Nov 11 2009, 10:02) *
Короче говоря единственно правильный вариант:
Код
twi_write_data(0,ptr, data[ptr]);
ptr++;

До единственно правильного далеко т.к. есть пара вопросов:
1. На кой в twi_write_data передавать "ptr"?
2. На кой индекс неверно обзывать поинтером?

Два единственно правильных варианта:

- twi_write_data( 0, *ptr++ )
- twi_write_data( 0, data[ i++ ] );
Go to the top of the page
 
+Quote Post
_Pasha
сообщение Nov 14 2009, 01:22
Сообщение #28


;
******

Группа: Участник
Сообщений: 5 646
Регистрация: 1-08-07
Пользователь №: 29 509



Цитата(Dima_G @ Nov 13 2009, 06:18) *
rolleyes.gif
Чет не пойму, что Вы имеете в виду laughing.gif

Коль скоро для volatile оптимизации запрещены, то разница между ++j и j++ (volatile j) должна наблюдаться на любых компиляторах.
Go to the top of the page
 
+Quote Post

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

 


RSS Текстовая версия Сейчас: 22nd July 2025 - 10:35
Рейтинг@Mail.ru


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