Jump to content

    

ARM7 сравнение компиляторов

Интересно с какой?

Если будет 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) ? Компилятор не может знать что это в вашем случае это не так =)

Share this post


Link to post
Share on other sites
А если 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

Share this post


Link to post
Share on other sites
&(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. Это ничего не меняет.

Share this post


Link to post
Share on other sites

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

 

Хотя вот:

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;

Share this post


Link to post
Share on other sites
Тоесть компилятор всегда перегружает переменную,если ранее была лябая запись в память?

 

Хотя вот:

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, то это очевидная ошибка программиста.

Share this post


Link to post
Share on other sites

В "голых" Сях есть квалификатор restrict для указателей для подобных целей. В плюсах его нет.

Share this post


Link to post
Share on other sites
нет указания компилятору что содержимое b может измениться. Поэтому если с указывает на b, то это очевидная ошибка программиста.

Тогда в случаи с next->prev=prev; prev->next=next; тоже нету явного указания компилятору, что prev может изменится. Ситуация аналогичная вроде? если next->prev == <cast...>&(prev->next) то это вероятно ошибка программиста.

В случаи с long logn/массивом можт быть и не ошибка, а модификация какого-то поля с флагами таким образом, хотя и не красивая. Вобщем мутно как-то. Тот же прикол, но вместо long long подсунуть short - перегружает short всегда после любой модификации памяти.

 

restrict вероде поддерживается(или заменяется на пробел, как и register :)) почти всеми плюсовыми компилерами, правда да, в стандарте его нету

Share this post


Link to post
Share on other sites
Тогда в случаи с next->prev=prev; prev->next=next; тоже нету явного указания компилятору, что prev может изменится. Ситуация аналогичная вроде? если next->prev == <cast...>&(prev->next) то это вероятно ошибка программиста.

...

Ситуация далеко не аналогичная. Просто прямое обращение по адресу и обращение двойное обращение по адресу.

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
Sign in to follow this