2010-07-19 27 views
8

Olası Çoğalt:
Could anyone explain these undefined behaviors (i = i++ + ++i , i = i++, etc…)Sonrası artır Operatör: Beklenmedik Davranış

Kodum aşağıdaki gibidir:

#include <stdio.h> 
int main() 
{ 
    int x = 10, y = 0; 
    x = x++; 
    printf("x: %d\n", x); 
    y = x++; 
    printf("y: %d\n", y); 
} 

sonrası artım doğasını göz önüne alındığında, aşağıdaki çıktıyı bekler:

x: 10 
y: 10 

benim akıl artışı gerçekleşir sonra hat 5, x başlangıç ​​değerinin tayin edilmesi gerektiğidir. Bu benim için kasıtlı bir seçim gibi görünüyor,

x: 11 
y: 11 

montaj içine Kazı:

LCFI2: 
     movl $10, -4(%rbp) // this is x 
     movl $0, -8(%rbp) // this is y 
     incl -4(%rbp)  // x is simply incremented 
     movl -4(%rbp), %esi 
     leaq LC0(%rip), %rdi 
     movl $0, %eax 
     call _printf 
     movl -4(%rbp), %eax // now x is saved in a register, 
     movl %eax, -8(%rbp) // copied to y, 
     incl -4(%rbp)  // and finally incremented 
     movl -8(%rbp), %esi 
     leaq LC1(%rip), %rdi 
     movl $0, %eax 
     call _printf 

Burada neler oluyor

Bunun yerine, ancak, bu olsun? GCC beni kendimden kurtarmaya mı çalışıyor? Kullanışlı bir dil referansım yok ama bunun amaçlanan semantiği bozduğunu düşünürdüm.

+0

iğrençlikleri olarak yazılabilir olur !!! –

+0

http://tr.wikipedia.org/wiki/Sequence_point – Ken

+0

Kötü eski günlerde, bazı dillerdeki a = 1 + a ', tüm yeni hataların başlayacağı bir maymundu. –

cevap

13

davranış tanımlanmamış, bakınız örn C FAQ. (Bu standarda göre tanımlanmamış olduğundan)

+0

Teşekkürler! Daha önce dizi noktalarının farkında değildim. – danben

4

Bu tam olarak bir yayın/ön-in/azaltma oluştuğunda C dili ile tanımsız bırakılır. Böylece, x = x++ gibi ifadeler iyi oluşturulmamıştır - bunları önlemek.

+1

Daha doğrusu, bir ifadede bir değişkeni bir kereden fazla değiştirmenize izin verilmez. 6.5/2: * "Bir önceki ve bir sonraki sıralama noktası arasında, bir nesne, bir ifadenin değerlendirilmesiyle en fazla bir defa depolanmış değerine sahip olacak." * – sth

+2

@ sth: Daha kesin olarak, "sıralama noktaları arasında birden fazla". Bir ifadenin bir sıralama noktası içermesi mümkündür; bu durumda, bir değişkeni birden çok kez değiştirmek iyi olur. Örneğin, '&&', '||' ve virgül operatörünün tümü tek bir ifade içinde sıra noktaları oluşturabilir. –

+0

@sth: Hatta _more precisely_, bu kodlayıcıda bir sınırlama değil, değişkenin kendisinde bir sınırlama. Sizin "izin vermediğiniz" ifadesi oldukça doğru değil. Siz _are_ izin, sadece yapmak için çok aptalca bir şey var :-) – paxdiablo

1

Eğer varsa: ne olup bittiğini

a = b++; 

o b kaydedilir ve ödev yapıldıktan sonra b birer 'artırılır. Tek yapmanız Yani eğer:

x = x ++; 

ve daha önce x 10 ne olacak 10 x kaydedilecek ve sonra (sizin Printf yapılır öncesi) x 11 yazdırılır yüzden 11'a birer 'artırılır. x = x++ hiçbir müdahale dizisi noktası olarak

2

Standartları yana, ran yolu onu beklerdik yoludur.

Zaman kural x++ bir hat için, x ile x++ yerine ve (ön kademe için ya da önceki hat) aşağıdaki satırda x += 1 koyulmasıdır. Başparmak o kuralın ardından

, kodunuz

#include <stdio.h> 
int main() 
{ 
    int x = 10, y = 0; 
    x = x; // x: 10 
    x += 1; // x: 11 
    printf("x: %d\n", x); 
    y = x; // y: 11 
    x += 1; // x: 12 
    printf("y: %d\n", y); 
}