SORU
29 Ocak 2012, Pazar


Biçim baskı işaretçi (Adres) belirleyici değil mi?

Hangi format belirtici yazdırmak için bir değişken adresini kullanarak olmalıdır? Çok arasında aşağıda kafam karıştı.

%u - işaretsiz tamsayı

%x - onaltılık değeri

%p - void işaretçi

Baskı için en uygun biçim olacağı bir adres olan?

CEVAP
29 Ocak 2012, Pazar


En basit cevap, farklı platformlar arasında formatında kaprisleri ve varyasyonları sakıncası varsayarak, %p standart gösterimde.

C99 standardı (IEC 9899:1999 ISO/) §7.19.6.1 ¶8'de diyor ki:

p bağımsız void gösterici olacaktır. İşaretçi değeri baskı karakter dizisi dönüştürülür, bir uygulama tanımlı şekilde.

C11 — ISO/IEC 9899:2011 — bilgi (§7.21.6.1 ¶8.)

Bazı platformlar, bu arasında bir lider 0x ve diğerleri olmayacak, ve harfler de olabilir içinde küçük harf veya büyük harf ve C standart değil hatta tanımlayan bu onaltılık çıktı ama biliyorum hiçbir uygulama yeri değildir.

Açıkça (void *) dökme ile işaretçileri dönüştürmek gerekir olup olmadığını tartışmaya oldukça açık. Genellikle iyi olduğu açık, ben ne kadar () ve standart diyor 'argümanı void gösterici olacaktır. Çoğu makinelerde, uzakta açık bir tonunu atlama ile olacaktı. Ancak, belirli bir bellek konumu için char * bir adres bit gösteriminde farklı bir makinede bu konu edebilirbaşka bir işaretçi< . em ^/ ' aynı bellek için adres konum. Bu kelime-ele, yerine byte-ele, bir makine olur. Bu makineler yaygın (muhtemelen değil) bu gün mevcut değildir, ama üniversiteden sonra çalıştığım ilk makine bir tür (tekstil müşterilerine Perq).

Uygulama tanımlı %p <inttypes.h> C99 kullanımı davranış ve uintptr_t yerine memnun değilseniz:

printf("0x%" PRIXPTR "\n", (uintptr_t)your_pointer);

Bu ince ayar gösterimi kendinize göre sağlar. Ben seçtiğiniz için hex basamaklı harf sayısını ise eşit bir şekilde aynı boy ve karakteristik dip başlangıç 0xA1B2CDEF görünür böylece, gibi 0xa1b2cdef dips yukarı ve aşağı birlikte sayısı çok. Seçim olsa da, çok geniş sınırlar içinde. (uintptr_t) dökme açıkça derleme zamanında biçim dizesi okumak varken GCC tarafından tavsiye edilir. Bu uyarıyı dikkate alıp bu şekilde çoğu zaman olacağını düşünenler var emin değilim gerçi, dökme isteği için doğru olduğunu düşünüyorum.


Kerrek yorum sorar:

Biraz standart promosyonlar ve variadic değişkenleri hakkında kafam karıştı. Tüm işaretçiler standart-terfi* void? Eğer int* Eğer yoksa, diyelim ki, iki bayt, ve void* 4 bayt, o zaman açıkça bağımsız olmayan dört bayt okumak için bir hata olurdu?

C standardı, tüm nesne işaretçileri aynı boyutta olması gerektiğini söylüyor izlenimini altındaydı, void * int * farklı boyutlarda olamaz. Ancak, C99 standardının ilgili bölüm bence ne kadar empatik değil doğrudur ben ne önerdi aslında yanlış bir uygulama bilmiyorum ama ():

§6.2.5 Türleri

¶26 işaretçi geçersiz karakter bir türü için bir işaretçi olarak temsil ve uyum gereksinimleri eder.39)Benzer şekilde, uyumlu türleri nitelikli ya da niteliksiz sürümleri için işaretçiler aynı temsil ve uyum gereksinimleri olacaktır. Tür yapı için tüm işaretçiler birbirleri olarak temsil ve uyum gereksinimleri eder. Birleşim türleri için tüm işaretçiler birbirleri olarak temsil ve uyum gereksinimleri eder. Diğer türleri için işaretçiler aynı temsil veya hizalama gereksinimleri yoktur.

39)Aynı temsil ve uyum gereksinimleri fonksiyonların dönüş değerleri ve sendika üyeleri bağımsız olarak değiştirilebilirlik ima etmek içindir.

(C11 bölümüne §6.2.5, ¶28 ve Dipnot olarak aynı 48.)

Yani, yapılar için tüm işaretçiler birbirleri ile aynı boyutta olması gerekir, ve göstericiler nokta yapıları farklı hizalama gereksinimleri var olsa bile aynı uyum gereksinimlerini paylaşmak gerekir. Sendikalar için aynı şey söz konusu. Karakter ve işaretçiler void işaretçiler aynı boyut ve hizalama gereksinimleri olması gerekir. int varyasyonları işaretçiler (unsigned int signed int anlamı) birbirine; diğer türleri için benzer olarak boyut ve hizalama gereksinimleri aynı olmalıdır. Ama C standardı resmen sizeof(int *) == sizeof(void *) böyle bir şey yok. Oh iyi, bu YÜZDEN sana varsayımlarını incelemek yapmak için iyidir.

C standart kesin olarak işlev işaretçileri nesne işaretçileri olarak aynı boyutta olması gerekmez. DOS gibi sistemlerde farklı bellek modelleri kırmamak için gerekliydi. Orada 16-bit veri işaretçileri ama 32-bit işlev işaretçileri, ya da tam tersi olabilir. Bu C standart bir işlev işaretçileri nesne işaretçileri ve tersi dönüştürülebilir dayatmaz neden olur.

Neyse ki (programcılar POSIX hedefleme için), POSIX ihlal adımları ve işlev işaretçileri ve veri işaretçileri aynı boyutta mandate:

§2.12.3 Pointer Types

Tüm fonksiyon işaretçi türleri türü void işaretçi aynı gösterime sahip olacaktır. void * için bir işlev işaretçisi dönüşüm gösterimini değiştirmek zorundadır. void * bir değeri, böyle bir dönüşüm kaynaklanan özgün işlev işaretçisi türü, açık bir tonunu kullanma, geri bilgi kaybı olmadan dönüştürülebilir.

Not: ISO C standardı bu gerekli değildir, ama POSIX uyumluluk için gereklidir.

printf() gibi variadic bir işlev için bir işaretçi geçirmeden, açık atmalarını görünüyor void * maksimum için şiddetle tavsiye edilir güvenilirliği kodu. POSIX sistemlerde, Güvenli Yazdırma için geçersiz bir işaretçi için bir işlev işaretçisi attı. Diğer sistemlerde, mutlaka güvenli, ne de göstericiler bir dökme olmadan void * dışında geçirmek için mutlaka güvenli bir yöntem değil.

Bunu Paylaş:
  • Google+
  • E-Posta
Etiketler:

YORUMLAR

SPONSOR VİDEO

Rastgele Yazarlar

  • case LianLi

    case LianLi

    28 Mayıs 2010
  • Kai Moosmann

    Kai Moosmann

    5 Temmuz 2006
  • Lena Danya

    Lena Danya

    11 NİSAN 2010