2016-11-07 38 views
5

garip davranışları Ben bir öğretim bilgisayar bilimleri için asistan ve ben öğrencilerimden biri bir tamsayı tek veya çift olup olmadığını kontrol etmek için aşağıdaki kodu ibraz: (en azından benim için) ŞaşırtıcıBir sayı C++ olup olmadığını kontrol edin. kod

int is_odd (int i) { 
    if((i % 2 == 1) && (i % 2 == -1)); 
    else; 
} 

bu kod verir doğru sonuç. 100000000'a kadar sayıları test ettim ve bu kodun neden olduğu gibi davrandığını açık bir şekilde açıklayamıyorum.

Biz bu yüzden tipik bir soru olmadığını biliyoruz

++ gcc v6.2.1 ve c kullanırken, ama bazı yardım bulmak istiyoruz. şey dönmeden bir fonksiyonun sonuna yola akan

+6

doğru sonuçları verir? İşlev bir int döndürmek, ancak hiçbir şey döndürmez. Davranışı tanımlanmamıştır. Sonuçların "doğru" olduğunu nasıl belirlediniz? – StoryTeller

+0

Gerçekten düzeltdiğinizde, bu hiç de doğru değil. http://ideone.com/5bs2aF – StoryTeller

+0

Davranış tanımsız. Bakın (burada) (http://melpon.org/wandbox/permlink/HbRsBuRh5fAnBA0U). Bir '0' veya' eax' buna göre, ancak ben onun [bu] (http gibi bir şey bakıyor sanırım çok kırılgan en iyi – krzaq

cevap

15

bakılmaksızın aslında derleyici nasıl işlediğine dair tanımsız davranış vardır. Eğer GCC için -O3 geçmesi veya Clang kullanırsanız, o zaman farklı sonuçlar elde unutmayın. Eğer x86 okuyamıyorsanız

push rbp 
    mov  rbp, rsp 
    mov  DWORD PTR [rbp-4], edi 
    mov  eax, DWORD PTR [rbp-4] 
    cdq 
    shr  edx, 31 
    add  eax, edx 
    and  eax, 1 
    sub  eax, edx 
    cmp  eax, 1 
    nop 
    pop  rbp 
    ret 

Merak etmeyin:

aslında "doğru" cevabı bakın neden gelince, bu GCC 6.2 -O0 de üretir x86 düzeneğidir. Unutulmaması gereken önemli şey eax dönüş değeri için kullanılır ve if deyimi için tüm ara hesaplamalar kendi hedef olarak eax kullanmalarıdır. İşlev çıktığı zaman, eax sadece şube denetiminin sonucuna sahip olur. Tabii

, bunların hepsi sadece akademik tartışma; Öğrencinin kodu yanlıştır ve ne tür testler yaptığınızı geçip geçmediğine bakılmaksızın kesinlikle sıfır puan veririm.

+2

Bunun kırılganlığı, çağrı düzenini değiştirerek daha da kanıtlanabilir. – StoryTeller

+1

Evet, kod yanlış olabilir, ama yine de neden hala işe yaradığını merak ediyordum, çünkü sistemin neden böyle davrandığını anlamak istiyorum. (Her iyi bilgisayar bilimcinin yapması gerektiği gibi;)) – DonMushroom

+0

Reddetmenin herhangi bir sebebi var mı? Belki de UB: D – TartanLlama