2013-11-14 51 views
6

MC9S12C32 mikro denetleyici için bazı gömülü C kodlarında, statik olarak boyutlandırılmış bir bayt dizisi ve kuyruk önü ve arkası için iki "işaretçi" ile uygulanan dairesel bir sıraya (eş dairesel arabellek) sahibim. gerçekte kuyruklar dizisi için sadece endeksler.C imzasız modül, derleyici uyarısına neden oluyor

trear arka elemanın gerçek endeks olmakla tfront (tabii 16 modülo tabi) ön eleman gerçek indeksi daha azdır biri olduğunu
// call unsigned chars bytes 
typedef unsigned char byte; 
byte trear = 0; // SCI transmit display buffer IN index 
byte tfront = 0; // SCI transmit display buffer OUT index 
byte tsize = 16; // size of transmit buffer 
byte tbuf[16]= {0};// SCI transmit display buffer 

Not. Yani, örneğin, eğer benim tampon "Merhaba", bu gibi görünebilir içeriyordu (boş yuvaları olan çöp değerler):

o kuyruktan bir bayt kaldırmak için zamanı geldiğinde, bunu
_________________________________ 
| | |h|e|l|l|o| | | | | | | | | | 
^  ^
front  rear 

:

// increment front index 
tfront++; 
// wrap front index if it exceeded bounds 
tfront %= tsize;       // (A) 
// get character to transmit 
byte outputChar = tbuf[tfront]; 

Tüm bunlar iyi çalışıyor - en azından, programım bu bölümle ilgili hiçbir hata göstermedi.

Uyarı: C2705: Veri

main.c hattı 402

Olası kaybını ben bu programı derlemek Ancak, benim derleyici hattı hakkında beni uyarıyor şikayet, yukarıda fragmanında (A) işaretlenmiş

Satır 402 satırı (A). Gcc veya benzeri kullanmıyorum; Freescale'in CodeWarrior IDE'sinde derleme yapıyorum, ki bu da bana bazen başka bir şekilde mistikleyici uyarılar verdi.

// increment front index mod tsize 
tfront = (tfront + 1 >= tsize) ? 0 : tfront + 1;  // (B) 
// get character to transmit 
byte outputChar = tbuf[tfront]; 

Ancak, benim derleyici hala aynı uyarıyı, hat (B) hakkında bu kez yayar: uyarı kurtulmak için bir girişim olarak, ben yukarıdaki fragmanı yeniden yazdım. Belki de derleyici bana bildirimde (tfront + 1 >= tsize), tfront ifadesinin yürütmeden önce 255 ve taşma olabileceğini söylüyor. Tabii ki, bunun olmayacağını biliyorum, ama derleyicim öyle değil.

Böyle bir durum söz konusu olsa da, neden satır (A) sorunluydu? Temel olarak, derleyicinin mutsuz olduğunu bilmek isterim.


sorumu yazarak beri, bir önişlemci tanımına değişken türünden tsize değiştirerek çözdük (yani #define TSIZE 16). Benim sorum yine de geçerli.


ilgili bazı sorular:
unsigned overflow with modulus operator in C
modulus operator with unsigned chars

+1

Not ve o da düzgünce önler cast olmadan bu uyarı. Yani 16 elemanlık bir tampon için 'tfront% = 16' yerine' tfront | = 0x0f' yerine. Genel bir durumda, 2'nin gücü olan “tsize” için gerekli olan mod-mask “tsize - 1” dir. – Clifford

+0

@Clifford Uyarı, lval = expr; 'lval' türü byte 've' expr '' int' türüne sahip olan atamanın genişletilmesiyle oluşursa, bit maskesi kullanmak uyarıdan kaçınmaz: ' tfront & = mask; 'tfront = tfront 'a genişler & mask;' ve 'tfront & mask' tür' int' türünde' tfront% size' aynı nedenden dolayı 'yapar (C99 6.3.1.1:2 ve 6.3.1.8:1 " Tamsayı promosyonları her iki işlenende gerçekleştirilir ”). –

+0

@Clifford Ayrıca, bitüm operatörüne doğru bir şekilde ulaşması gerekiyor. Bunu mu demek istediniz? –

cevap

5

derleyici uyarısı olasılıkla olmasından kaynaklanır (çünkü ifade tfront % tsize sahiptir C tanıtım kurallarının, tfront = tfront % tsize; eşdeğerdir tfront %= tsize;, o *) int yazın.

Bunun yerine, tfront = (byte)(tfront % tsize); yazarsanız, derleyiciyi susturabilir.

endişe özel bir nedeni yoktur, ve derleyici aslında garip uyarılar yayar: anlatım tfront % tsize teknik int, onun değerler tüm çünkü hesaplanır şekilde bir byte sığacak tip olmasına rağmen. Değerlerin tümü byte'a uygun olmasa bile, sarmalama davranışı işaretlenmemiş tamsayı türleri için C standardı tarafından güvence altına alınır (böylece, bu sarmalama davranışını amaç doğrultusunda kullanarak haklı çıkarsınız).

(*) bu tip unsigned int olacağını ve bu durumda bir unsigned char alabilir tüm değerleri içeremez ve muhtemelen uyarı görmemeniz sizin derleme platformu int üzerinde sürece.

+0

Önerdiğiniz gibi, bu sorun görünüyor. Çok anlayışlı, teşekkürler. – ravron

+2

Uyarı, tek başına yararsızdır; yanlış pozitifler yanlış negatiflerden daha kötüdür çünkü zihin setini zayıflatırlar 'uyarılar olmadan derleme iyidir'. Bir hatayı derleyici tedarikçisine bildirin. –

+0

@JonathanLeffler Bu hatayı birkaç yıl önce kendim bildirdim. Hala orada olup olmadığından emin değilim. Detaylar için cevabımı görün. – Lundin

3

Bu özel uyarı, tüm Codewarrior derleyicilerinde bilinen bir hatadır. Olası veri kaybı kaybı tutarsız ve buggy. Bazen uyarır, çünkü örtülü tür promosyonlar riski vardır, bazen yoktur. this discussion'a bakın. Bunun S12C için CW için de geçerli olduğunu doğrulayabilirim (en azından, kullandığım şey olan 5.1 sürümü kadar).

Bu uyarıyı devre dışı bırakabilirsiniz, ancak bazen yanlış uyarılarla birlikte tehlikeli kod bulduğu için bunu önermem. Özel durumunuzda olduğu gibi: uyarı doğrudur.

Açık artırma olmadan küçük tamsayı türlerinde aritmetik yapıyorsunuz. Böyle bir kod tehlikelidir ve muhtemelen gizli hatalar içerir, çünkü C imzalanmış küçük harflere küçük tamsayılar sağlar. MISRA-C gibi, açık atımları zorlayan bir kodlama standardı burada yardımcı olabilirdi. Nasıl çalıştığını bilmedikçe, ©: operatör de tehlikeli olabilir. 2. ve 3. operandı birbirine karşı dengeliyor, ki bu da muhtemelen beklemiyordu.

Bu nedenle kod değiştirerek öneririm: tsize` 2 nin kuvveti olması garanti edilebilir `eğer, biraz maskesi kullanmak daha verimli olduğunu

tfront = (byte)(tfront % tsize); 
... 

if((byte)(tfront +1) >= tsize) 
{ 
    tfront = 0; 
} 
else 
{ 
    tfront++; 
} 
+0

Sizin (byte) (tfront +1)> = tsize' öneriniz tarafından ikna olmadım. Sorunun asıl durumundan farklı olması gereken tek fırsat, (byte) (tfront +1) 'in' tfront + 1''den farklı olup olmadığı ve önerilen durumun sonucunun büyük olasılıkla olmamasıdır. programcının ne istediği.Derleyici uyarılarının, normalde bir olamayacağınız bir hatayı koymaya zorlamadığından emin misiniz? Türleri eşleştirmek istiyorsanız, '(imzasız int) tfront +1> = (imzasız int) tsize' muhtemelen daha iyidir. –

+0

@PascalCuoq Evet, bu satırdaki oyuncuların bir kısmı seçicidir, sadece tyd = 255 gibi bazı nadir durumlarda sorun çıkarır. Sıfıra kaydırma, imzasız değişkenler için iyi tanımlanmış olduğundan, programcı bu davranışa dayanan kodu yazmışsa, beklendiği gibi çalışmayacaktır çünkü 'tfront' dolaylı olarak terfi edilir. Çarpıcı tanıtımla ilgili hatalar ve garipliklerle ilgili sorun her zaman tam olarak şudur: programcı aslında neyi amaçladı? Bir tuhaflık olmasını beklediler mi yoksa sürpriz olarak mı onlara geldi? Bu gibi durumlarda kodda yorum yazmak çok önemlidir. – Lundin

İlgili konular