SORU
10 ŞUBAT 2011, PERŞEMBE


&; Kaldırma" işaretçi demek " ne demektir?

Bir işaretçi çözümlemesi için ne ifade ediyor? Bir örnek ile bir açıklama alabilir miyim?

CEVAP
10 ŞUBAT 2011, PERŞEMBE


Temel terminolojinin gözden geçirilmesi

genellikletasavvur bir programlama Meclisi değilsen - - yeterince iyiişaretçisayısal bir bellek adresi içeren, 1 işlemin bellekte ikinci bayt atıfta ile, 2 üçüncü, 3 dördüncü ve benzeri....

  • 0 ve ilk bayt ne oldu? Peki, bunu daha sonra göreceğiznull işaretçileraşağıda.
  • Göstericiler mağaza ve bellek ve adresleri ile nasıl daha doğru bir tanım için bkz"Muhtemelen bilmesine gerek yok neden bellek adresleri hakkında daha fazla".

İşaretçi - nümerik dizin adresi sonra içeriğini gösteren hafızasında data/değer erişmek istediğiniz zamaninceleyebilirsinizişaretçi.

Farklı bilgisayar dilleri şimdi ilgilendiğiniz derleyici veya yorumlayıcı anlatmak için farklı gösterimler sivri-değer - aşağıda ben focus C ve C . var

İşaretçi bir senaryo

C düşünün, aşağıda p gibi bir işaretçi verilen...

const char* p = "abc";

...dört bayt ile sayısal değerleri kodlamak için kullanılan harfleri 'a', 'b', 'c', 0 baytlık belirtmek sonuna metinsel veri, saklı bir yerde bellek ve sayısal adres veri saklanır p.

Eğer dize adresi 0x1000 p bir at olsaydı eğer örneğin, 0x2000, bellek içeriği de 32-bit işaretçi olabilir:

Memory Address (hex)    Variable name    Contents
1000                                     'a' == 97 (ASCII)
1001                                     'b' == 98
1002                                     'c' == 99
1003                                     0
...
2000-2003               p                1000 hex

Adres için değişken isim/tanımlayıcı 0x1000, ama dolaylı olarak dize bakın biz bir işaretçi adresini saklamak kullanarak değişmez diye bir şey yok not: p.

İşaretçi kaldırma

Karakterleri biz p Puan başvurmak için p Bu notlar (yine C için): kullanarak inceleyebilirsiniz

assert(*p == 'a');  // the first character at address p will be 'a'
assert(p[1] == 'b'); // p[1] actually dereferences a pointer created by adding
                     // p and 1 times the size of the things to which p points:
                     // in this case they're char which are 1 byte in C...
assert(*(p   1) == 'b');  // another notation for p[1]

Ayrıca gitmek gibi sivri, onları kaldırma veri: ile işaretçileri taşıyabilirsiniz

  p;  // increment p so it's now 0x1001
assert(*p == 'b');  // p == 0x1001 which is where the 'b' is...

Eğer yazılabilir bazı veriler varsa, o zaman bu gibi şeyler yapabilirsiniz:

int x = 2;
int* p_x = &x;  // put the address of the x variable into the pointer p_x
*p_x = 4;       // change the memory at the address in p_x to be 4
assert(x == 4); // check x is now 4

Yukarıda da olmalısın bilinen derleme zamanında size gereken bir değişken adı x ve kodu sorar derleyici için organize olması gereken yere saklanan, sağlama adresi olacak mevcuttur) * &x.

Ve yapı veri üyesi erişim kaldırma

Eğer veri üyeleriyle bir yapısı olan bir değişken varsa C, üyelerini -> kaldırma operatörü kullanarak erişebilirsiniz:

typedef struct X { int i_; double d_; } X;
X x;
X* p = &x;
p->d_ = 3.14159;  // dereference and access data member x.d_
(*p).d_ *= -1;    // another equivalent notation for accessing x.d_

Multi-byte veri türleri

Bir işaretçi, bir bilgisayar programı da ihtiyacı var biraz kavrama içine türde veri olması sivri - eğer bu veri türünde birden fazla bayt temsil, işaretçinin normal puan en küçük numaralı bayt veri.

Yani, biraz daha karmaşık bir örnek bakarak:

double sizes[] = { 10.3, 13.4, 11.2, 19.4 };
double* p = sizes;
assert(p[0] == 10.3);  // knows to look at all the bytes in the first double value
assert(p[1] == 13.4);  // actually looks at bytes from address p   1 * sizeof(double)
                       // (sizeof(double) is almost always eight bytes)
assert(  p);           // advance p by sizeof(double)
assert(*p == 13.4);    // the double at memory beginning at address p has value 13.4
*(p   2) = 29.8;       // change sizes[3] from 19.4 to 29.8
                       // note: earlier   p and   2 here => sizes[3]

İşaretçiler Dinamik Bellek tahsis edilir

Bazen ne kadar program çalışıyor ve veri atılan ne olduğunu görene kadar gerekir bilmiyorum... sonra Dinamik Bellek malloc kullanarak ayırabilirsiniz. Bir işaretçi adresini saklamak için kullanılan bir uygulamadır

int* p = malloc(sizeof(int));   // get some memory somewhere...
*p = 10;            // dereference the pointer to the memory, then write a value in
fn(*p);             // call a function, passing it the value at address p
(*p)  = 3;          // change the value, adding 3 to it
free(p);            // release the memory back to the heap allocation library

C , bellek ayırma normalde new operatörü ile yapılır, ve delete ile kaldırma:

int* p = new int(10);   // memory for one int with initial value 10
delete p;

p = new int[10];      // memory for ten ints with unspecified initial value
delete[] p;

p = new int[10]();    // memory for ten ints that are value initialised (to 0)
delete[] p;

Ayrıca BkzC akıllı işaretçileraşağıda.

Ve adresleri sızıntı kaybetme

Genellikle bir işaretçi bazı veri ya da Tampon Bellek içinde bulunduğu tek belirtisi olabilir. Eğer sürekli kullanım verileri/tampon gerekli, ya da yetenek arama free() delete önlemek için sızıntı bellek programcı gerekir ameliyat bir kopyası... işaretçisi

const char* p = asprintf("name: %s", name);  // common but non-Standard printf-on-heap

// replace non-printable characters with underscores....
for (const char* q = p; *q;   q)
    if (!isprint(*q))
        *q = '_';

printf("%s\n", p); // only q was modified
free(p);

...ya da dikkatli bir şekilde planlamak ters herhangi bir değişiklik...

const size_t n = ...;
p  = n;
...
p -= n;  // restore earlier value...

C akıllı işaretçiler

C smart pointer nesneler ve işaretleyiciler, otomatik olarak onları ayırmayı kaldırma depolamak ve yönetmek için kullanmak için en iyi uygulama akıllı işaretçiler' yıkıcılar çalıştırın. C 11 beri Standart Kütüphane iki, unique_ptr ayrılmış bir nesne için tek bir sahibi var... sağlar

{
    std::unique_ptr<T> p{new T(42, "meaning")};
    call_a_function(p);
    // the function above might throw, so delete here is unreliable, but...
} // p's destructor's guaranteed to run "here", calling delete

...ve hisse sahipliği için 68* *(reference counting kullanarak)...

{
    std::shared_ptr<T> p(new T(3.14, "pi"));
    number_storage.may_add(p); // might copy p into its container
} // p's destructor will only delete the T if number_storage didn't copy

null işaretçiler

C, NULL 0 - ve ayrıca C nullptr - kullanılabilir olduğunu gösteren bir işaretçi değil, şu anda sahip bellek adresi bir değişken, ve olmamalı başvuru yapıldı veya kullanılan işaretçi aritmetiği. Örneğin:

const char* p_filename = NULL; // or "= 0", or "= nullptr" in C  
char c;
while ((c = getopt(argc, argv, "f:")) != EOF)
    switch (c) {
      case f: p_filename = optarg; break;
    }
if (p_filename)  // only NULL converts to false
    ...   // only get here if -f flag specified

Dahili sayısal türler mutlaka false ** 47, ne de bools varsayılan yok gibi C ve C işaretçileri her zaman 50 ** ayarlanmamış. Tüm bunlar 0/yanlış/BOŞ zaman static değişkenler veya (C) doğrudan ya da dolaylı olarak üye değişkenleri statik nesneler ya da üslerini veya tabi sıfır başlatma (örneğin new T(); new T(x, y, z); gerçekleştirin sıfır hazırlama T üyeleri de dahil olmak üzere göstericiler, oysa new T;).

Ayrıca, ne zaman atama 0, NULL 57* bir işaretçi bit işaretçi değildir, tümünü Sıfırla: işaretçiyi içeremez "0" donanım seviyesi, ya da başvurmak için adres 0 sanal adres alanı. Derleyici izin verilir saklamak için başka bir şey varsa vardır bir sebebi, ama ne olursa olsun yapar - eğer gelin ve karşılaştırın işaretçisi 0, NULL, nullptr veya başka bir işaretçi oldu atanan tüm olanlar, karşılaştırma çalışmak gerekir beklendiği gibi. Derleyici düzeyinde kaynak kodu, "" potansiyel olarak biraz "" C ve C dilleri.... büyülü BOŞ yani

Muhtemelen bilmesine gerek yok neden bellek adresleri hakkında daha fazla, ve

Daha sıkı başlatıldığını işaretçiler, bit desen de belirlenmesi NULL ya da bir (genellikle virtual) bir bellek adresi saklayın.

En basit durumda bu bir sayısal mahsup işlemi tüm sanal adres alanı; daha karmaşık durumlarda işaretçi olabilir göre bazı özel hafıza alanı, hangi İŞLEMCİ olabilir seçin tabanlı CPU "segment" kaydeder veya bazı şekilde kesim kimliği kodlanmış bit-desen ve/veya seyir içinde farklı yerlere bağlı olarak makine kod talimatlarını kullanarak adresi.

Örneğin, bir int* düzgün intialised işaret etmek için int değişken olabilir - sonra döküm için bir float* - erişim değeri "GPU" hafıza oldukça farklı gelen int değişken, sonra bir kez oyuncular için bir işlev işaretçisi olabilir başvurmak için ayrı bellek holding makine işlem kodları için işlevi.

C ve C gibi programlama dilleri * Boris kırmızı ® 3gl bu karmaşıklığı, bu tür şeyleri saklamak eğilimindedir:

  • eğer derleyici size bir işaretçi değişken veya işlev olabilir inceleyebilirsiniz serbestçe (değişken değil yok/kaldırıldı bu arada) ve derleyici sorunu olup olmadığını örneğin, belirli bir CPU kaydetmek gerekiyor restore önceden, veya ayrı bir makine kodu talimat kullanılır

  • eğer bir işaretçi için bir öğe bir dizi kullanabilirsiniz işaretçi aritmetiği taşımak başka bir yerde dizi, hatta form adresi bir-son--son dizisi bu yasal karşılaştırmak ile diğer göstericiler için öğeleri bir dizi (veya buna benzer bir şekilde taşındı tarafından işaretçi aritmetiği için aynı bir-son-uç değer); yine C ve C , bu kadar derleyici sağlamak bu "işe yarıyor"

  • örneğin, paylaşılan bellek eşleme fonksiyonları sana öğüt verebilir, ve onlar olacak işletim sistemi belirli bir "iş" içinde onlar için bir anlam ifade eden adresler

  • girişimleri taşımak yasal işaretçiler ötesinde bu sınırları veya atama rasgele sayılar işaretçiler, işaretçi dökme alakasız tipleri, genellikle undefined behaviour, bu yüzden kaçınılmalıdır yüksek düzeyde kütüphaneler ve uygulamaları, ama kod için ÖSS, aygıt sürücüleri, vb. Mayıs davranışı tanımsız-daha iyi , belirli bir donanım tarafından tanımlanan C veya C, bıraktığı güvenmek gerekir.

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

YORUMLAR

SPONSOR VİDEO

Rastgele Yazarlar

  • Kai Moosmann

    Kai Moosmann

    5 Temmuz 2006
  • LaKe Lightroom Tutorials

    LaKe Lightro

    22 Temmuz 2014
  • TheOtherMau5

    TheOtherMau5

    6 Mart 2012