2012-02-29 15 views
21

intptr_tvoid* yerine genel amaçlı bir depolama (işaretçileri ve tamsayı değerlerini korumak için) kullanmak iyi bir fikir midir? (As burada görülen: http://www.crystalspace3d.org/docs/online/manual/Api1_005f0-64_002dBit-Portability-Changes.html) Zaten okuduklarıma içinIntidr_t yerine void *?

:

  • int ->void* ->int gidiş dönüş orijinal değerini tutmak için garanti edilmez; Ben int tahmin ->intptr_t ->int depolanması tamsayı
  • değerleri zaman intptr_t az yayınları demektir hem void* ve intptr_t yayınları gerekir, bu nedenle hiçbiri işaretçileri saklarken
  • void* az açık yayınları anlamına burada avantaj alır üzerinde
  • işaretçi Arithmetics yapacak
  • intptr_t C99 gerektirir
ben dikkate alması gereken başka ne

?

+0

Hayır. (Eğer öyleyse, o zaman sadece intptr_t'ın semantiklerini 'void *' e eklediler) –

+0

"Sorar" ("işaretçileri ve tamsayı değerlerini tutmak için"), ancak sonra yalnızca "int", " * 've' intptr_t'. 'Uintmax_t', 'size_t',' long long' vb. Ayrıca tamsayı türleridir, soru gibi sesler sadece nesne işaretçileri, 'intptr_t' ve' int' türleri ile ilgilidir. – chux

cevap

25

yerine void* arasında (işaretçileri ve tamsayı değerleri tutmak için) bir genel amaçlı depo olarak intptr_t kullanmak iyi bir fikir mi?

sayılı

intptr_t mevcudiyeti garanti edilmez. İlk olarak, not ettiğiniz gibi C99'da tanıtıldı. İkincisi, uygulamalar, bilgi kaybı olmadan dönüştürülmüş işaretçi değerlerini tutacak kadar büyük bir tamsayı türüne sahip olmak zorunda değildir. bilgiler silinir fakat intptr_tint daha geniş olduğunu hiçbir gerçek garantisi yoktur bir int olası is geri intptr_t ve dönüştürme

.

İşaretçi değerlerini kaydetmek istiyorsanız, bunları işaretçi nesnelerinde saklayın. İşaretçi nesneleri budur.

bir nesne ya da eksik tipine herhangi bir işaretçi bilgi kaybı olmadan tekrar tekrar void* dönüştürülür ve edilebilir. İşlevlerin göstergeleri için böyle bir garanti yoktur - ancak herhangi bir işaretçi-işlev türü, bilgi kaybı olmaksızın herhangi bir başka işaretçi-işlev türüne dönüştürülebilir. (C standardına atıfta bulunuyordum; POSIX'in bazı ek garantiler sağladığını düşünüyorum.)

Aynı nesneye bir tamsayı veya işaretçi değeri kaydetmek istiyorsanız, yapmanız gereken ilk şey yeniden düşünmektir. senin tasarımın. Bunu zaten yaptıysanız ve bunu gerçekten yapmak istediğinizi belirttiyse, bir sendika kullanmayı düşünün (ve en son ne tür bir değer kaydettiğinizi dikkatlice takip edin).

İsteğe bağlı verilerin geçirilmesine izin vermek için void* bağımsız değişkenini kullanan API'ler vardır; Örneğin, POSIX pthread_create() işlevine bakın. Bu, bir tamsayı değeri void*'a dökerek kötüye kullanılabilir, ancak bir tamsayı nesnesinin adresini geçirmek için daha güvenlidir.

+2

Lütfen "_unlikely_ bilgi kaybetmek" için genişletin. 'intptr_t', bir karşılaştırıcıya _equally_ bir işaretçi gidiş-dönüş yapar - Bu, muhtemelen aynı olmayan desen yorumunuzun bilgi kaybıdır. – chux

+2

@chux: Dediğim gibi, 'intptr_t'' ın int'den daha geniş olduğunu (hiçbir yerde uygulama olmadığını bilmeme rağmen) garanti yoktur. Örneğin, "intptr_t", 32 bit ve "int" 64 bit ise, daha sonra bir "int" yi "intptr_t" ve "int" olarak geri dönüştürmek bilgiyi kaybedebilir. Özellikle, int 'değeri intptr_t' aralığının dışındaysa, ilk dönüşüm uygulama tanımlı bir sonuç verir. –

+2

Maalesef, yanıtı "_prointer_ dosyasını" intptr_t'ye dönüştürme ve geri bilgi kaybı olasılığı düşük ... "şeklinde yanlış okuyun. Yorumum bu düşünceye dayanıyordu. Int/intptr_t sorunlarının nadirliği hakkında katılıyorum. – chux

5

Hayır, herhangi bir türün hem işaretçileri hem de tam sayıları depolamanın makul bir yolu olduğunu ve bunun yanı sıra kodunuzu karıştırmasını garanti edemezsiniz. Daha iyi bir yol var. Eğer bir tamsayı ve aynı nesnede bir işaretçi saklamak istiyorsanız

, temiz ve taşınabilir yöntem bir birlik kullanmaktır:

union foo { 
    int integer_foo; 
    void *pointer_foo; 
} 

Bu taşınabilir ve sen şeylerin her iki türlü depolamasına olanak tanır İkisinin büyüklüğü için gereken depolama alanı. Her zaman işe yaraması garanti edilir.

+1

'int' ve' void * 'düzen açısından genel bir başlangıç ​​dizisine sahip midir? Aksi takdirde, bu _not_ portatiftir, her iki üyeyi bir kerede depolayabilmeniz için _not_ 'tanisiniz ve bu kesinlikle "her zaman çalismak" için kesinlikle _not_ garantilidir. –

+3

Sendika tanımından sonra bir '' 'eksik olduğundan emin olun. – Shoe

+1

@LightnessRacesinOrbit İki değerin aynı anda depolanabileceğini iddia ettiğini sanmıyorum. "her ikisi", bir "int" nin içinde saklanabileceği ve bir "boşluğun" içinde saklanabileceği anlamına gelir, fakat eşzamanlılık önerisi yoktur. NB. Bu kuralın yalnızca yapılarda geçerli olması nedeniyle, int 've' void * 'nin ortak başlangıç ​​sırasına sahip olmasının önemi yoktur. –