eine gerade oder ungerade Zahl unterscheiden
-
Interessant wäre noch, ob Compiler hinreichend intelligent sind, um
int x = ...; int y = ( x % 2 + 2 ) % 2;
zu optimieren.
-
camper schrieb:
Interessant wäre noch, ob Compiler hinreichend intelligent sind, um
int x = ...; int y = ( x % 2 + 2 ) % 2;
zu optimieren.
Hoffentlich hab ich alles richtig entziffert.
movl $_ZSt3cin, %edi //&cin laden nach edi leaq 12(%rsp), %rsi //&x laden nach rsi call _ZNSirsERi //op<< aufrufen movl 12(%rsp), %esi //y=x //also erstmal in ein register tun movl $_ZSt4cout, %edi //&cout laden nach edi andl $1, %esi //y = ( y % 2 + 2 ) % 2; //optimiert call _ZNSolsEi //op>> aufrufen
Da guckstu. Wiedermal der magische gcc.
-
Die Frage ist bei solchen Sachen immer (zumindest für mich), ob da einer aus Langeweile ein spezielles Pattern implementiert hat oder ob das ein allgemeiner Mechanismus ist.
-
Du kannst dich ja in den GCC-Sourcen auf die Suche machen.
-
Bashar schrieb:
Die Frage ist bei solchen Sachen immer (zumindest für mich), ob da einer aus Langeweile ein spezielles Pattern implementiert hat oder ob das ein allgemeiner Mechanismus ist.
Da alles konstant ist, kriegt der Compiler das locker mit den allgemeinen Regeln hin. Was für ein spezielles Pattern soll das denn sein?
-
nurf schrieb:
Da alles konstant ist, kriegt der Compiler das locker mit den allgemeinen Regeln hin.
x ist nicht konstant. Und so locker kann das nicht sein, der MSVC kann das z.B. nicht.
-
Ist leider tatsächlich nur eine spezielle Behandlung für gewisse Zahlen.
cin >> x; int y = ( x % 1000 + 1000 ) % 1000; cout << y << '\n'; int z = (unsigned)x % 1000; cout << z << '\n';
führt zu
call _ZNSirsERi movl 8(%rsp), %esi movl $_ZSt4cout, %edi movl %esi, %eax imull %ebx // (1) movl %esi, %eax sarl $31, %eax sarl $6, %edx subl %eax, %edx imull $1000, %edx, %edx subl %edx, %esi addl $1000, %esi movl %esi, %eax imull %ebx // (2) movl %esi, %eax sarl $31, %eax sarl $6, %edx subl %eax, %edx imull $1000, %edx, %edx subl %edx, %esi call _ZNSolsEi movq %rbp, %rsi movl $1, %edx movq %rax, %rdi movb $10, 15(%rsp) call _ZSt16__ostream_insertIcSt11char_traitsIcEERSt13basic_ostreamIT_T0_ES6_PKS3_l movl 8(%rsp), %esi movl $_ZSt4cout, %edi movl %esi, %eax mull %ebx shrl $6, %edx imull $1000, %edx, %edx subl %edx, %esi call _ZNSolsEi movq %rbp, %rsi movl $1, %edx movq %rax, %rdi movb $10, 15(%rsp) call _ZSt16__ostream_insertIcSt11char_traitsIcEERSt13basic_ostreamIT_T0_ES6_PKS3_l
also 2 Divisionen (durch Multiplikation ersetzt) im ersten Fall.