2012-08-03 20 views
10

Eski bir koddan gcc uyarılarını kaldırıyorum.Nasıl giderilir: C kodunda "farklı boyuttaki tam sayıdan işaretçiyi göster" uyarısı?

example: 

some_struct *ptr = func() // func() returns an integer. 

Birisi nasıl böyle gcc uyarıları gidermek için bana yol misiniz:

o tiplemeleri ile "farklı boyutta tamsayı gelen işaretçi döküm" uyarısı bastırmak mümkün mü?

+7

Neden bir tamsayı bir struct işaretçisine yerleştirmek istersiniz? – Jay

+0

Mümkün, ancak bunun doğru yoldan gitmesinin gerektiği durumlar nadirdir. –

+0

"çıkış" farklılıklarının aşırı yüklenmesi var mı? (Giriş parametreleri değil) –

cevap

19

İlk olarak, func düzeltilebilseyim (kaynağını değiştirmesine izin verilir), ardından düzeltin. Hesaplamaları işaretçilerle yapılıyorsa, bunları işaretçilerle ve dönüş işaretçileriyle yapın. Bazen, adreslerle tamsayı olarak çalışmak için geçerli nedenler vardır (ör. Özel kodda hizalama sorunlarını ele alma). Bu durumda, uintptr_t türünü (stdint.h numaralı belgede tanımlanmış) kullanmak için func'u değiştirin. Gerekli olduğunda işaretleyicileri tamsayı olarak işlemek için tasarlanmıştır. (İmzalanmış bir aritmetik herhangi bir nedenle daha iyi ise intptr_t da vardır, ancak genellikle imzasız uintptr_t daha az sorunlu buluyorum.) Tercihen, func, döndürürken bir işaretçi için uintptr_t dönüştürmelidir, bu nedenle func dönüş türü bir işaretçi (belki de some_struct veya void için).

func düzeltemiyorsanız, derleyiciye gerçekleştirilmekte olan dönüştürmeleri yapmayı planladığını söylemek için yayınları kullanabilirsiniz. Ancak, bu belirli hata iletisi, yalnızca bir tamsayıyı bir işaretçiye dönüştürmediğinizi, ancak bir boyuttaki bir tamsayıyı (örneğin, dört bayt) başka bir boyuttaki bir göstericiye (ör., Sekiz bayt) dönüştürdüğünüzü bildirmektedir. Bu kod ilk olarak func tarafından döndürülen tamsayı türünün işaretçi türü ile aynı boyuta sahip olduğu bir sistem için yazılmıştır, ancak şimdi işaretçi türünün tamsayı boyutundan daha büyük veya daha küçük olduğu bir sistem üzerinde derleme yapıyorsunuzdur. Bu durumda, func tarafından gerçekleştirilen hesaplamaların yeni mimaride çalıştığından emin olmalısınız. Sadece 32 bitlik bir değer döndürüyorsa, her zaman doğru değeri koruyacak mı? Yani, eksik olan 32 bitlik hiçbir şey kaybolacak mı? func'un hesaplaması gereken adres, kullandığı tamsayı türünün maksimum değerini geçmez mi? func işaretli tamsayı türleri kullanıyorsa, işaret biti de düşünün.

func tarafından döndürülen değerin doğru olduğundan emin olmanız durumunda, some_struct *ptr = (some_struct *) (intptr_t) func(); gibi açık yayınları kullanabilirsiniz.

6

Gcc, bahsettiğiniz uyarıyı vermiyor. Aynı zamanda garip olurdu çünkü kodunuzda hiç oyuncu yok.

ben uyarısını

assignment makes pointer from integer without a cast 

Not "alçıda olmadan" kısmı olsun. Eğer uymuyor func dönüş türü IFF sizin uyarı ("farklı boyutta tamsayı gelen işaretçi döküm") alacak Sonra

some_struct *ptr = (void*)func(); 

: Böylece (davranışını değiştirmeden) döküm yoluyla sessiz gcc yapabilirsiniz adresler için Bu, uygun bir tamsayı tipine func() dökümünü ek olarak, örneğin: intptr_t: Eğer gerçekten bir işaretçi yanlış ölçekli tamsayı dönüştürmek istediğiniz varsayımı altında

some_struct *ptr = (void*)(intptr_t)func(); 

Bütün bunlar. Muhtemelen, kodu yeniden işlemek daha iyi bir fikirdir. iki olasılık Burada bir

3

şunlardır:

  1. func bir tam gerçek bir işaretçi döküm edilir; daha sonra bir işaretçi olarak kullanılır. Bir işaretçide saklanmakta olan bir tamsayıya dönüyorsa
  2. ptr daha sonra bir tam sayıya dönüştürülür ve bir tamsayı olarak kullanılır. İlk durumda

, func dönüş değeri bilgi kaybedecek ve int Windows çoğunda 64-bit memory models (dahil olacak bir veri işaretçisi boyutu küçükse potansiyel kötü çökmesine veya ve Linux). Bu durumda, func dönüş türünü intptr_t; Using intptr_t instead of void*? ve Why/when to use `intptr_t` for type-casting in C?'a bakın.

İkinci durumda, daha az sorun var, ancak intptr_t: some_struct *ptr = (some_struct *)(intptr_t)func(); ve daha sonra int value = (int)(intptr_t)ptr; aracılığıyla atmanız gereken endianness sorunları ile başa çıkmak. Sorunun bir açıklaması için bkz. GLib Type Conversion Macros.