|
Порядок выполнения операций. Вопрос зантокам! |
|
|
|
Nov 11 2009, 06:33
|

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

|
Что сделает компилятор увидев такой код: Код twi_write_data(0,ptr, data[ptr++]);
|
|
|
|
|
Nov 11 2009, 06:49
|

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

|
Цитата(HARMHARM @ Nov 11 2009, 12:45)  Сделает вызов функции. Если найдет соответствующий заголовок. Объясните свой вопрос. Зантоки и телепаты в отпуске. Допустип ptr==0, с какими параметрами будет вызвана функция twi_write_data()
|
|
|
|
|
Nov 11 2009, 07:32
|
Местный
  
Группа: Свой
Сообщений: 279
Регистрация: 2-07-08
Из: Новосибирск
Пользователь №: 38 699

|
Цитата(igorenja @ Nov 11 2009, 10:33)  Что сделает компилятор увидев такой код: Код twi_write_data(0,ptr, data[ptr++]); Компилятор - скомпилирует. А вот что сделает программа - не определено, тк компиляторозависимо. Вобщем - бэдстайл
|
|
|
|
|
Nov 11 2009, 07:53
|

Частый гость
 
Группа: Свой
Сообщений: 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
|
|
|
|
|
Nov 11 2009, 08:02
|

Частый гость
 
Группа: Свой
Сообщений: 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++;
|
|
|
|
|
Nov 11 2009, 09:45
|

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

|
Цитата(igorenja @ Nov 11 2009, 10:02)  Короче говоря единственно правильный вариант: Код twi_write_data(0,ptr, data[ptr]); ptr++; Вообще-то правильнее привыкнуть писать в таких местах ++ptr. Потому что ptr может оказаться сложным типом, при ptr++ может быть создана лишняя копия.
|
|
|
|
|
Nov 11 2009, 12:34
|
Местный
  
Группа: Свой
Сообщений: 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++) Функционально одинаковы, но первая - оптимальнее
|
|
|
|
|
Nov 11 2009, 12:47
|
Местный
  
Группа: Свой
Сообщений: 279
Регистрация: 2-07-08
Из: Новосибирск
Пользователь №: 38 699

|
Цитата(esaulenka @ Nov 11 2009, 15:37)  HARMHARM, а можно пример? Не понимаю... надеюсь, ув. HARMHARM не будет против, если я отвечу  на пальцах - в случае постинкремента мы 1) изменяем состояние объекта 2) возвращаем предыдущее состояние объекта (вот для сохрения предыдущего состояния как раз и создается копия) в случае прединкремента мы 1) изменяем состояние объекта 2) возвращаем новое состояние - сохранять старое состояние объекта не требуется
|
|
|
|
|
Nov 11 2009, 12:55
|

Знающий
   
Группа: Свой
Сообщений: 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++) Функционально одинаковы, но первая - оптимальнее  Бред какой ... Только что проделал такое с VC 6. Результирующий exe-файл в обоих случаях идентичный (проверено тотал коммандером).
--------------------
Сделано в Китае. Упаковано в России.
|
|
|
|
|
Nov 11 2009, 13:04
|

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

|
Никогда не задумывался... Но разве ptr++ - это не "сначала использовать переменную ptr, а потом её инкрементировать", а именно "создать копию, инкрементировать один экземпляр, а использовать другой" ? К тому же, на мой взгляд, i++ читается лучше, чем ++i. Во всяком случае, я когда вижу ++i, начинаю задумываться, зачем оно тут применяется
--------------------
Тут обсуждается творческий порыв, а не соответствие каким-либо стандартам ©
|
|
|
|
|
Nov 11 2009, 16:15
|
Местный
  
Группа: Свой
Сообщений: 279
Регистрация: 2-07-08
Из: Новосибирск
Пользователь №: 38 699

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

Гуру
     
Группа: Свой
Сообщений: 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
|
|
|
|
|
Nov 12 2009, 04:31
|
Местный
  
Группа: Свой
Сообщений: 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_)); }
Причина редактирования: Уменьшение видимого размера цитаты исходника.
|
|
|
|
|
Nov 12 2009, 08:00
|
Местный
  
Группа: Свой
Сообщений: 279
Регистрация: 2-07-08
Из: Новосибирск
Пользователь №: 38 699

|
Цитата(Flexz @ Nov 12 2009, 11:56)  У Страуструпа, кстати, там где int - постинкремент, а там где итератор - прединкремент Со встроенными типами практически всегда это без разницы - компилятор соптимизирует  (хотя, вдруг выйдет новая интересная платформа + сырой комиплятор  ) Но лично мне не нравится такой зоопрак из ++i и i++ в программе  Поэтому пишу единообразно, используя ++i
|
|
|
|
|
Nov 13 2009, 13:46
|

кекс
     
Группа: Свой
Сообщений: 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++ ] );
|
|
|
|
1 чел. читают эту тему (гостей: 1, скрытых пользователей: 0)
Пользователей: 0
|
|
|