2015-07-07 14 views
5

[...] Uyarı: tanımsız davranışı: Uçucu erişimlerin sırası bu hat tanımsız davranıştır Neden bu açıklama x.cpp xxxBu tanımlanmamış davranış için gerekçe nedir?

tanımlanmamış?

volatile short const *VREFINT_CAL = (short *) 0x1FFFF7BA; 

ve

volatile STRUCT_ADC_DR *ADC_DR = (STRUCT_ADC_DR*) 0x40012440; 

tarafından tanımlanan:

typedef struct 
{ 
    unsigned DATA   : 16; 
    unsigned    : 16; 
} STRUCT_ADC_DR; 

bunu mi derleyici konusunda emin olmadığı için beyanlar/ilklenmeleri olan

case 2: 
    Vdda = 3.3 * (*VREFINT_CAL)/ADC_DR->DATA; 

uçucu elemanlar farklı davranabilir erişildikleri sırada? (Durum nedir?)

Ancak, hesaplamalar aynı önceliklere sahip olduğundan, hesaplamanın soldan sağa doğru yapılmasını sağlamamalı mıyım?

+0

Eğer 'volatile' ne yaptığını bildiğinden emin misin:

mesele bazı geçici, sadece ara sıra noktası eklemek için kullanın çözmek için? Ve kodunuzda neden kodlanmış adresler var? – deviantfan

+1

Sanırım bu, “standardı neden tanımsız bir davranış olarak açık bir şekilde işaretliyor/bunun mantığı nedir?”, Aksi takdirde çok sayıda insanın “standardı öyle” diyeceksin. – OMGtechy

+6

İşlenenlerin değerlendirme sırası belirtilmemiş. – molbdnilo

cevap

10

volatile, derleyici için normal bir bellek adresi olmayan bir G/Ç bağlantı noktası gibi bir şey okuduğunuz anlamına gelir. Bu tür iki okuma için, bu okumaların belli bir düzende gerçekleşmesini isteyeceksiniz.

Hem C hem de C++ 'da, işlenenlerin değerlendirme sırası tanımlanmamıştır. Eğer size yardımcı olur, bir işlev çağrısı olarak bölünme düşünüyorum:

Vdda = 3.3 * divide(*VREFINT_CAL, ADC_DR->DATA); 

nokta şimdi, işte bu düzen önemlidir olasıdır volatile için, derleyiciye bu kararı ayrılmak istemeyebilir . Bu yüzden bu konuda uyardı.

Uyarıdan kurtulmak için, kodunuza ek sıralama noktaları ekleyerek siparişi açıkça verin. Örneğin:

short const x = *VREFINT_CAL; 
unsigned const y = ADC_DR->DATA; 
Vdda = 3.3 * x/y; 
+2

Çok haklısınız. Değeri sıfırlamak için DATA VREFINT_CAL'den önce erişildiğinde büyük bir sorunla karşılaşabilirim. – dhein

+0

@Zaibis Uyarının aslında bu durumda bir hata yakalamanıza yardımcı olduğunu duyduğuma sevindim. – ComicSansMS

+0

@Zaibis Alf, size, "Sorun mu var?" Sorusuna yanıt verirken, verilerinize ve uygulamalarınızın bunları nasıl ele aldığına bağlı olarak tam olarak söyler. Derleyici, işin, bunun ötesindeki her şeyden uzak olduğu için sorunlara * neden olabileceğini söylüyor. – edmz

4

Eğer değerlendirmenin ait düzen ve öncelik arasındaki farkı bilmek zorunda Bunu anlamak için.

örneğin, ifadeyi ele alalım:

Vdda = 3.3 * (*VREFINT_CAL)/ADC_DR->DATA; 

Öncelik (ve parantez) soyut sözdizimi ağacı (AST) oluşturulma biçimi belirler. Sonuç şöyle olur:

= 
    Vdda 
    * 
    3.3 
    /
     * 
     VREFINT_CAL 
     -> 
     ADC_DR 
     DATA 

Değerlendirme sırası sıralama noktalarının varlığıyla belirlenir. Ve kodunuzun, ifadenin sonunda (;) yalnızca bir sıra noktası vardır. Bu nedenle herhangi bir alt ifadenin değerlendirilme sırası belirtilmemiş olur. Yani derleyici, uygun gördüğü herhangi bir sırayla herhangi bir ara hesaplama ve hafıza erişimi yapabilir. Bazı insanlar, alt ifadelerin soldan sağa doğru değerlendirildiğini düşünmeyi severler, fakat bu dilin işleyiş şekli değildir.

Normalde herhangi bir fark yapmaz, ancak alt ifadelerin iki volatile (*VREFINT_CAL ve ADC_DR->DATA) böylece sipariş konularda vardır. Belki sizin için önemli değil, ama kesinlikle derleyicide önemlidir.

short a = *VREFINT_CAL; 
unsigned b = ADC_DR->DATA; 
Vdda = 3.3 * a/b; 
+0

@Zaibis: Evet, evet.Ama yine de yerel bir değişkene ihtiyacınız var: 'kısa a; a = * VREFINT_CAL, b = ADC_DR-> VERİ, Vdda = 3,3 * a/...; '. Eğer yapmaya çalışırsanız: 'Vdda = 3.3 * (0, * VREFINT_CAL)/...;' bu işe yaramaz. – rodrigo

İlgili konular