Sie können nichts von einer dieser Operationen annehmen, eine Kompilierung könnte beide zu den gleichen Anweisungen optimieren.
Und in der Tat, beide clang
und gcc
übersetzen sie in eine einzige and
Anweisung.
Leider aufgrund der Natur von %
mit einem angegebenen Rückgabewert für negative Werte seit ISO C99, ist einige zusätzliche Arbeit für signed
ganze Zahlen erforderlich. Im Gegensatz zu ISO C90, wo negativer Modulo implementiert wurde.
Die resultierende Anordnung für beide Operationen auf beiden signed
und unsigned
Werte:
modulo
mit signierten Zahlen:
mov eax, DWORD PTR [esp+4] ; grab `val`
cdq ; convert 32-bit EAX to 64-bit
; and fill EDX with the sign bit
shr edx, 30 ; shift EDX by 30 positions to the right
; leaving only the two left-most bits
add eax, edx ; add EDX to EAX
and eax, 3 ; do the AND
sub eax, edx ; subtract EDX from EAX
mov DWORD PTR [esp+8], eax ; move result on stack
Dieser netter Trick ist, haben richtig für negative Werte definiert Verhalten. Es macht ((val + 3) & 3) - 3
für negative Werte und val & 3
für positive.
and
mit/ohne Vorzeichen und modulo
mit unsigned:
mov eax, DWORD PTR [esp+4]
and eax, 3
mov DWORD PTR [esp+12], eax
Sie können nie etwas annehmen, was oder wie der Compiler optimiert. Der Standard überlässt dies explizit dem Compiler. Und falls Sie nicht nur den Rest, sondern auch den Quotienten benötigen, [siehe div()] (http://en.cppreference.com/w/c/numeric/math/div). – DevSolar
Jeder einigermaßen moderne Compiler wird bei diesen Arten von Mikrooptimierungen ** weit ** jeden Menschen übertreffen. Verwenden Sie immer das Konstrukt, das am deutlichsten die Absicht darstellt. – sp2danny
Nein, Sie können nicht wirklich davon ausgehen, dass der Compiler den Code immer optimieren wird. Ja, '&' ist normalerweise schneller. Was du schreibst, sollte das sein, was du wirklich vorhast. – Ian