2012-08-06 24 views
5

Olası Çoğalt:
GCC left shift overflowBeklenmeyen sol vardiyalı davranışı

aşağıdaki asgari programı düşünün. Ben MinGW altında GCC ile derleme beklenen gibi

#include <stdint.h> 
#include <stdio.h> 

int main() 
{ 
    uint32_t v = 1024; 
    v &= (((uint32_t)1 << 32) - 1); 
    printf("v = %u\n", v); 
    return 0; 
} 

Bu 1024 yazdırır. 1 tane 32 kez sola kaydığı için tekrar 0 olduğu için 0-1 = -1 olan "1111 .... 1111" dir. Bu AND'ed herhangi bir değerle aynı değeri tekrar döndürmelidir. Ben

#include <stdint.h> 
#include <stdio.h> 

int main() 
{ 
    unsigned int s = 32; 
    uint32_t v = 1024; 
    v &= (((uint32_t)1 << s) - 1); 
    printf("v = %u\n", v); 
    return 0; 
} 

programı değiştirirseniz

Ancak baskılı sonuç artık 0 olduğunu. Birisi bu davranışı açıklayabilir mi?

cevap

7

32 bitlik bir değeri 32 bit olarak değiştirmek, C cinsinden tanımlanmamış bir davranıştır. Bunu yapmayın.

+0

http://catb.org/jargon/html/N/nasal-demons.html –

6

Her ikisi de tanımlanmamış davranışlardır, çünkü kaydırma mesafesi türün bit genişliğinden daha az olmalıdır. Sabit ile, gcc'nin optimiser beklediğiniz şeyi yapar, ancak değişkenle, vardiya çalışma zamanında yapılır. Muhtemelen vardiya mesafesi 31 ile maskelenir, bu nedenle vardiya yapılmaz ve 1 - 1 == 0