2012-03-09 27 views
43

Bir diziden oluşan dizeleri bir diziden diziye okumak zorunda olduğumuz bir ödev yapıyorum. Dizide bir şifreleme algoritması aramak zorundayım (şifre 2B dizileri aktarır). Bu nedenle, öncelikle tüm bilgileri dosyadan bir 2D diziye koydum, fakat kodumun geri kalanında çakışan türlerle ilgili bir sürü sorun yaşadım (özellikle char [] 'a char *' ı ayarlamaya çalışıyorum). Bu yüzden, kodumun çoğunda her şeyi çok daha kolaylaştıran bir dizi işaretçiye geçmeye karar verdim.Char [] 'dan char *' a dönüştürmek mümkün mü?

Ama şimdi char * 'a ve tekrar geri dönmem gerekiyor, ancak tekrar anlayamıyorum. Google'da hiçbir şey bulamadım. Mümkün mü diye merak etmeye başladım.

+1

[comp.lang.c SSS] 'in 6. bölümünü okuyun (http://c-faq.com/). –

cevap

87

İşaretçiler ve diziler arasında kafanız karışmış gibi geliyor. (Bu durumda char * ve char [] olarak) işaretçiler ve dizileri bir dizi char a[SIZE]a konumunda değeri SIZE

  • bir işaretçi char *a; diyor uzunlukta bir dizi olduğunu söyler not the same thing.

    • olduğu yerde değeri of a, char'un bir işaretçisidir.

      char a[] = "hello"; // array 
      
          +---+---+---+---+---+---+ 
      a: | h | e | l | l | o |\0 | 
          +---+---+---+---+---+---+ 
      
      char *p = "world"; // pointer 
      
          +-----+  +---+---+---+---+---+---+ 
      p: | *======> | w | o | r | l | d |\0 | 
          +-----+  +---+---+---+---+---+---+ 
      
      : Bu, bir dizi gibi davranmaya işaretçi Aritmetik birleştirilebilir hafızasında

    , bu (the FAQ alınan örnek) şöyle (örneğin, a[10]a puan her yerde son 10 girdidir)

    Birçok durumda, bir dizi referansı, ilk öğeye bir göstericiye "bozulur" çünkü, işaretçiler ve diziler arasındaki fark konusunda kafa karıştırılması kolaydır. Bu, birçok durumda (bir işlev çağrısına geçirildiğinde olduğu gibi) dizilerin işaretçi haline geldiği anlamına gelir. Daha fazlasını öğrenmek isterseniz, this section of the C FAQ describes the differences in detail.

    Büyük bir pratik fark, derleyicinin bir dizinin ne kadar sürdüğünü bilmesidir. Yukarıdaki örnekler kullanarak: kodunuzu görmeden

    char a[] = "hello"; 
    char *p = "world"; 
    
    sizeof(a); // 6 - one byte for each character in the string, 
          // one for the '\0' terminator 
    sizeof(p); // whatever the size of the pointer is 
          // probably 4 or 8 on most machines (depending on whether it's a 
          // 32 or 64 bit machine) 
    

    , bu en iyi hareket tarzını tavsiye etmek zor, ama ben şu anda yaşıyorsanız sorunlarını çözecek her yerde işaretçileri kullanmak değişiyor zanlısı.Şimdi şunu not ediniz:

    • Dizilerin nerede olduğu her yerde belleği başlatmanız gerekecektir. Örneğin, char a[10];, char *a = malloc(10 * sizeof(char)); olur ve bunu a != NULL olarak kontrol eder. Bu durumda, sizeof(char)'u gerçekten söylemeniz gerekmediğini unutmayın, çünkü sizeof(char) 1 olarak tanımlanmıştır. Tamlık için onu bıraktım.

    • yerde daha önce (eğer dizeleri kullanıyorsanız, sen '\0' kadar sayar, hangi strlen() kullanabilirsiniz) Eğer ayrılan belleğin uzunluğu ile değiştirilecektir gerekecektir dizi uzunluğu için sizeof(a) vardı. Her bir çağrı malloc() için free() numaralı aramaya karşılık gelen bir çağrı yapmanız gerekecektir. Bu, yaptığınız bilgisayarı malloc() ile istediğiniz anıyı kullanarak bildirir. Eğer işaretçiniz a ise, free(a); kodunu, a puanına ihtiyacınız olan herhangi bir şeye ihtiyacınız olmayan bir noktaya yazmanız yeterlidir.

      char* p = &a[0] 
      

      Sen Char işaretçi p adresi haline gelir" olarak okuyabilir: Başka bir cevap olarak

    Bir dizide başlangıç ​​adresini almak istiyorsanız, kullanabileceğiniz işaret [0] numaralı telefonun a numaralı ".

  • +7

    +1 Harika yanıt –

    +0

    Son örnekte, 'char * p = & a [0]' basitleştirilemez, sadece char * p = & a? –

    +1

    @thom_nic: Hayır, çünkü '& a', 'char (*) [6]' türüne, yani altı karakterlik bir diziye işaretçi. Bu, char * 'ile aynı değildir, bu yüzden bir uyarı alırsınız. Bununla birlikte, "char * p = a;' diyebilirsiniz, çünkü bir dizi referansı [ilk elementine bir göstergeye dönüşebilir] (http://c-faq.com/aryptr/aryptrequiv.html). Burada daha uzun formu kullandım, çünkü neler olduğunu daha iyi gösteriyor. –

    9

    sen [1] *(d+1) yaparak, vb

    +0

    oh, teşekkürler! Bunu deneyeceğim. – tparf

    +0

    Ya da sadece char * d = c; 'olabilir. – mah

    -4

    Eh, sorunuzu anlamak emin değilim c char[] c o zaman char* d = &c[0] ve erişim elemanı yapabileceği varsa ...

    C, Char [] ve Char * aynı şeydir.

    Düzenleme: Bu ilginç bağlantı için teşekkürler.

    +2

    Korkarım ki bu doğru değil - [işaretçiler ve diziler C ile aynı şey değildir] (http://www.lysator.liu.se/c/c-faq/c-2.html) –

    +0

    ama derleyici bana bir hata veriyor :( – tparf

    +0

    @TimothyJones: SSS için daha iyi bir bağlantı http://c-faq.com/ ve tabii ki% 100 doğru konum: diziler ve işaretçiler değil * * Ve aynı şey. (Ve "char", "Char" değil, yazıldığından önemlidir.) –

    2

    Onları işaretçi olarak kullanmak isterseniz, bunları diziler olarak bildirmeniz gerekmez. İşaretçiyi çok boyutlu dizilermiş gibi referans alabilirsiniz. Sadece bir işaretçi bir işaretçi olarak oluşturun ve malloc kullanın:

    int i; 
    int M=30, N=25; 
    int ** buf; 
    buf = (int**) malloc(M * sizeof(int*)); 
    for(i=0;i<M;i++) 
        buf[i] = (int*) malloc(N * sizeof(int)); 
    

    ve sonra buf[3][5] ya da her neyse başvurabilir.

    +3

    'malloc()' sonucunu yayınlama. –

    +0

    Bu gereklidir çünkü 'malloc() işlevi' 'f '' içinde saklanacak bir' int * 'a basılması gereken bir' void * 'döndürür. – Arcinde

    +4

    Hayır, döküm gerekli değildir. C'de, "void *" türünde bir ifade, dolaylı olarak herhangi bir gösterici-nesne (veya işaretçi eksik) türüne dönüştürülebilir. [Comp.lang.c SSS] 'in 7.7b'sini (http://c-faq.com/) ve [C standardının 6.5.16.1 bölümündeki soruya bakın (http://www.open-std.org/ JTC1/SC22/wg14/www/docs/n1570.pdf). (C++, C++ 'yı tartışıyorsak uygun olabilecek farklı kurallara sahiptir.) –