2016-04-10 15 views
1

Bir boşluk işaretçisini doğrudan soruna neden olmadan uzun kestirmek mümkün mü? Aşağıda, here kodundan çıkarılan küçük bir kod pasajı var (örneğin, sayfanın Pthread Katılımı bölümü). this manual page gibiType-casting void * to long

{ 
    void *status; 
    long t; 
    rc = pthread_create(&thread[t], &attr, BusyWork, (void *)t); 
    rc = pthread_join(thread[t], &status); 
    printf("Main: completed join with thread %ld having a status of %ld\n",t,(long)status); 
} 

pthread_join() kopya hedef dişin çıkış durumu (yani hedef iplik pthread_exit() verilen bu değer) konuma bunda * dönüş_değeri (* durumlarına göre işaret söylüyor vaka). Ama bahsettiğim programda, durum herhangi bir yere işaret etmiyor. Öyleyse program hala nasıl çalışıyor?

Ve ikincisi, benim bilgim söz konusu olduğunda, durum uzun bir değer tutamazsa o zaman, typecasting durumu bize uzun ve bir adres olmayan bir değer verir?

+1

yinelenen: Busywork() fonksiyonuna geri tarafından gerçek değerini almak:

rc = pthread_create(&thread[t], &attr, BusyWork, (void *)&t); 

Ardından 'sorun'

Not kaybolur

:

kullanarak öner // stackoverflow .com/questions/12949383/converting-primitive-data-type-to-void-pointer-type? –

+0

@MartinR: [Bu] (http://man7.org/linux/man-pages/man3/pthread_join.3.html), ** pthread_join() öğesinin hedef iş parçacığının çıkış durumunu kopyalar. pthread_exit (3) 'e sağlanan hedef iş parçacığının * retval ** ile işaret ettiği yere değeri.Ama bahsettiğim programda, _status_ herhangi bir yere işaret etmiyor, o zaman bu program nasıl çalışıyor? –

+0

Bu tesadüfen çalışır. Değişken durumu başlatılmamıştır, bu yüzden durumun işaret ettiği yere yazacaktır. Şans eseri, yasal bir yerde olabilir. Eğer yasa dışı bir yerde ise, bir kaza olacak. – cup

cevap

1

Hızlı cevap: uzun * bir boşluğa sığacak şekilde garanti edilmez: Hayır,

Uzun cevap intptr_t kullanın. Bazı sistemlerde (özellikle 64 bit Intel Linux makineleri), void * ve uzun zamandır hem 64 bitlik miktarlarda çalışacak hem de Intel işlemcinin başka tipte farklılıkları bulunmuyor. 32-bit Intel Linux gibi diğer makinelerde bu makineler üzerinde 64-bit ve void * 32-bit olduğu için çalışmayacaktır. Daha egzotik makineler farklı özelliklere sahiptir.

Int < -> işaretçi dönüştürmelerini destekleyen standart tür stdint.h dosyasında bulunan intptr_t'dir. göre POSIX Programcı Kılavuzu:

herhangi bir geçerli işaretçi bu tip dönüştürülebilir geçersiz mülk ile işaretli tamsayı tipi, daha sonra bir işaretçi geri dönüştürülür atar şu tip geçersiz etmek ve sonuç orijinal pointer eşit karşılaştırır:

intptr_t Yani intptr_t olduğunu * gelen dönüşümleri desteklemek ve geçersiz garantilidir belirtilmemiş uzunlukta bir imzalı tamsayı türü. Ayrıca imzasız uintptr_t vardır.

Here is the definition of intptr_t in glibc. Gördüğünüz gibi, 64-bitlik makinelerde intptr_t ve long gerçekten de aynı tipte.

+0

Bu dokümanlar 'intptr_t', herhangi bir işaretçinin değerini tutamaz, tersi değil. Örneğin, işaretçiler 32 bit ve "intptr_t" 64 bit ise, gereksinimleri karşılar. (Yani, işaretçiden tamsayıya ve geriye doğru çalışacaktı.) Ben karşı mülkiyete sahip olacak herhangi bir tür olduğunu düşünmüyorum. – Nemo

+0

Bu iyi bir nokta, glibc kaynağının okunmasına rağmen aslında bu özel uygulama ile çalışacağından emin olduğumu hissediyorum. Ama standardın gerekli olmadığını kabul ediyorum. Açıklamak için cevabımı düzenlemek için çekinmeyin. – jforberg

0

bu satırı:

rc = pthread_create(&thread[t], &attr, BusyWork, (void *)t); 

doğru değil. http

long myVar = *parmVoidPtr;