9

gcc 4.9 ile gömülü ARM programlama yapıyorum. Şirketimin varsayılan dev araç yapılandırmasında olduğu için -Wconversion anahtarını kullanıyorum. Ben stdint.h types (uint8_t, uint32_t, vb) kullanıyorum.gcc derleyici uyarılarını kaldırmak için typecasting kullanma

derleyici uyarısı Bir bileşik atama ve hatta basit toplama işlemini her zaman oluşturur. Örneğin: here ve here tartışıldığı gibi

uint8_t u8 = 0; 
uint16_t u16; 

// These cause warnings: 
u8 += 2; 
u8 = u16 >> 8; 

Bunu düzeltmek için "yaygın yöntem", alçı kullanmaktır:

bu çirkin olmasının yanı sıra
u8 = (uint8_t)(u8 + 2); 
u8 = (uint8_t)(u16 >> 8); 

, ben inandırıcı kanıt olarak yayınlanmaya devam döküm genellikle kötü bir uygulamadır.

Sorularım:

  1. Neden bu şekilde tipleştiriyor kullanmak kötü?
  2. -Wconversion'u atlayıp derleyicinin benim için örtülü dönüşümler yapmasına izin vererek herhangi bir şeyimi kaybeder miyim?
+0

Bu durumda, yazım hatası hakkında 'kötü' bir şey yoktur. Eğer bir şey varsa, anlambilimsel, aritmetik, kesik, vb. Gibi anlamlarını düşündüğünüzü gösterir - ve bundan memnun kalırsınız. –

+0

@BrettHale, en azından cast *, tüm etkileri düşündüğünüz ve bunlardan memnun olduğunuz * iddiaları. Sen yapmasan bile, ya da değilsin. –

+1

@BrettHale, derleyiciyi kapatmanın olası hatalı kodlardan daha fazla önem vermesi durumunda oraya yayın yapabilir (scoff yapmayın - bu olur). Tüm etkileri düşündüğünüzü düşünüyorsanız, bunu yapabilirsiniz, ama yanılıyorsunuz. Ya da daha iyisini bilmiyor olsan bile. Dökümün doğası gereği olmadığını, mutlaka * kötü * olduğunu kabul ediyorum, ancak ilk etapta dökülme gerekliliğinden kaçınmak * daha iyi *. –

cevap

3

) derleyici uyarı susmasını hale getirecektir. Sahip olduğunuz koddaki sorun, C dilinde, aritmetik hiçbir zaman int'dan daha dar olan türde yapılmaz: derleyici her zaman int için örtük bir dönüşüm gerçekleştirir.

Çok etkili bir şekilde kodunuz, dar imzalanmamış türleri int'a dönüştürüyor, işlemi yapıyor ve sonra imzasız türe dönüştürüyor.

Genellikle dar tiplerle aritmetik yapmak iyi bir fikir değildir. Sadece depolama boyutu bir sorun ise bunları kullanın (genellikle diziler gibi daha büyük yapılar olacaktır). Yerelde, daha çok veya daha az geçici değişkenler bu dar tipler anlamsızdır.

3

O tadı meselesi. Farklı bir aritmetik türden bir nesneye aritmetik bir değer atadığınızda, C tarafından hiçbir zaman bir döküm gerekmez. Bazı insanlar döküm işlemini kullanarak gizli bir dönüşüm olduğunu ve bunu amaca uygun hale getirdiklerini belgeliyor. Şahsen

ekstra işe yaramayan eşyaları koymak için sevmiyorum ve ben okuyucu C temellerini bilir varsayıyorum bu yüzden döküm önlemek eğilimindedir (ve -Wall hatta -Wextra bir parçası olmadığı -Wconversion kullanmayın Neyse). Bir atamada, sağ taraftaki bir yazının sol taraftaki nesneye sığmaması durumunda, gcc genellikle atama UB olmasa bile (-Wall veya -Wextra olmadan) uyarır.

2

maket ile sorun onlar değil mi bile, "Ben ne yaptığımı biliyorum, sus" derleyici söylemek olmasıdır. Birisi, değişkenin 255'ten büyük değerleri işleyebildiğine ve uint16_t türünü değiştireceğine karar verirse, u8 + = 2 çalışır, ancak u8 = (uint8_t) (u8 + 2) kırılır. Değişkenin u8 değil "numberOfParagraphs" olarak adlandırıldığını varsayarsak, bu bulmak çok zor bir hata olabilir.

İlk etapta daha büyük bir türü kullanmak daha iyidir. Gerçekten, gerçekten (u8 + 2) & 0xff dosyasını saklamak istemediğiniz sürece, bu şekilde yazıp daha büyük bir değişkeni problemsiz olarak saklayabilirsiniz.

(Şahsen ben kendi türüne bir lvalue döküm etkisi yoktur semantik ile

(uint8_t)u8 += 2; 

gibi dilin bir uzantı istiyorum ve uyarı çıkarmadan, ama bir lvalue döküm sırasında bir lvalue kalır farklı tip bir hata olacağını etmek. Bu güvenli derleyici değil atmalarını yaparak, değiştirmeyi düşünmelisiniz ki size potansiyel sorun noktalar gösteriyor

İlgili konular