Petka 0 6 июля, 2012 Опубликовано 6 июля, 2012 · Жалоба Интересно с какой? Если будет next==prev всеравно поля next->prev,prev->prev и next->next,prev->next будут иметь разные адреса. Если next==prev==this тогда this->prev=this; this->next=this; Чет никак не могу придумать, как можно добится разного поведения от этих двух разных реализаций... апд. сории,в коде перепутал местами, но сути это не меняет,компилится так же.должно быть так next->prev=prev; prev->next=next; 11a: e9d0 1200 ldrd r1, r2, [r0] 11e: 604a str r2, [r1, #4] 120: e9d0 1000 ldrd r1, r0, [r0] 124: 6001 str r1, [r0, #0] А если next->prev == &(prev->next) ? Компилятор не может знать что это в вашем случае это не так =) Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
brag 0 6 июля, 2012 Опубликовано 6 июля, 2012 · Жалоба А если next->prev == &(prev->next) ? Компилятор не может знать что это в вашем случае это не так =) &(prev->next) Имеет тип tormoz**, а next->prev tormoz* . просто так оно не может быть присвоено. Тогда уж и компилятор не должен ничего удалять в таком случаи: volatile int t; void f(char *v){ *v=3; t=4; *v=5; } Вдруг v=&t , он же не может этого знать. тем не менее: gcc-4.7.1 00000000 <_Z1fPc>: 0: f240 0300 movw r3, #0 4: f2c0 0300 movt r3, #0 8: 2204 movs r2, #4 a: 601a str r2, [r3, #0] c: 2305 movs r3, #5 e: 7003 strb r3, [r0, #0] 10: 4770 bx lr armcc-4.1 00000000 <_Z1fPc>: 0: 4a51 ldr r2, [pc, #324]; (148 <__sti___10_kernel_cpp+0x20>) 2: 2103 movs r1, #3;<<--- Хохма 4: 2104 movs r1, #4 6: 6011 str r1, [r2, #0] 8: 2105 movs r1, #5 a: 7001 strb r1, [r0, #0] c: 4770 bx lr Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Petka 0 6 июля, 2012 Опубликовано 6 июля, 2012 · Жалоба &(prev->next) Имеет тип tormoz**, а next->prev tormoz* . просто так оно не может быть присвоено. Это программистом в явном виде так присвоено не может быть. А через приведение типов может быть как угодно. Ну тогда уж и компилятор не должен ничего удалять в таком случаи: volatile int t; void f(char *v){ *v=3; t=4; *v=5; } Вдруг v=&t , он же не может этого знать. тем не менее: Тут другой случай. v всегда указывает на одну и ту же ячейку памяти и запись в t ничего не может изменить. v может указывать куда угодно, хоть на t. Это ничего не меняет. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
brag 0 6 июля, 2012 Опубликовано 6 июля, 2012 · Жалоба Тоесть компилятор всегда перегружает переменную,если ранее была лябая запись в память? Хотя вот: char b[5]; int f(long long *c){ *c=1; b[2]=1;b[3]=2; return *c+b[3]; } 00000000 <_Z1fPx>: 0: 2300 movs r3, #0 2: 2201 movs r2, #1 4: f240 0100 movw r1, #0 8: e9c0 2300 strd r2, r3, [r0] c: f2c0 0100 movt r1, #0 10: 2301 movs r3, #1 12: 708b strb r3, [r1, #2] 14: 2302 movs r3, #2 16: 70cb strb r3, [r1, #3] 18: 2003 movs r0, #3 1a: 4770 bx lr Возвращает всегда 3. А вдруг c пересекается с b? тогда результат будет далеко не 3 ztest1.cpp: extern char b[5]; int f(long long *c); int main(){ printf("%d\n",f((long long*)&b)); return 0; } g++ -O1 -c ztest.cpp g++ -O1 ztest1.cpp ztest.o result=33619971 g++ -O2 -c ztest.cpp g++ -O1 ztest1.cpp ztest.o result=3 2 файла, абы компилятор не видел реализации функции f; Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Petka 0 6 июля, 2012 Опубликовано 6 июля, 2012 · Жалоба Тоесть компилятор всегда перегружает переменную,если ранее была лябая запись в память? Хотя вот: char b[5]; int f(long long *c){ *c=1; b[2]=1;b[3]=2; return *c+b[3]; } ...... Тут компилятор волен оптимизировать. т.к. char b не обьявлен как volatile т.е. нет указания компилятору что содержимое b может измениться. Поэтому если с указывает на b, то это очевидная ошибка программиста. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Сергей Борщ 116 6 июля, 2012 Опубликовано 6 июля, 2012 · Жалоба В "голых" Сях есть квалификатор restrict для указателей для подобных целей. В плюсах его нет. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
brag 0 6 июля, 2012 Опубликовано 6 июля, 2012 · Жалоба нет указания компилятору что содержимое b может измениться. Поэтому если с указывает на b, то это очевидная ошибка программиста. Тогда в случаи с next->prev=prev; prev->next=next; тоже нету явного указания компилятору, что prev может изменится. Ситуация аналогичная вроде? если next->prev == <cast...>&(prev->next) то это вероятно ошибка программиста. В случаи с long logn/массивом можт быть и не ошибка, а модификация какого-то поля с флагами таким образом, хотя и не красивая. Вобщем мутно как-то. Тот же прикол, но вместо long long подсунуть short - перегружает short всегда после любой модификации памяти. restrict вероде поддерживается(или заменяется на пробел, как и register :)) почти всеми плюсовыми компилерами, правда да, в стандарте его нету Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Petka 0 6 июля, 2012 Опубликовано 6 июля, 2012 · Жалоба Тогда в случаи с next->prev=prev; prev->next=next; тоже нету явного указания компилятору, что prev может изменится. Ситуация аналогичная вроде? если next->prev == <cast...>&(prev->next) то это вероятно ошибка программиста. ... Ситуация далеко не аналогичная. Просто прямое обращение по адресу и обращение двойное обращение по адресу. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться