2011-06-24 17 views
9

kişi.'char (* p) [5];' ifadesinin anlamı nedir?

Ben bu üç bildirimleri arasındaki farkları kavramak çalışıyorum: okuma bildirimleri ve bunun gibi şeyler her rehber yardım etmedi, çünkü

char p[5]; 
char *p[5]; 
char (*p)[5]; 

bazı testler yaparak bu bulmaya çalışıyorum ben şimdiye kadar Bu küçük program yazdım ve o (Ben üçüncü beyanının kullanımının diğer tür denedim ve seçeneklerin bitti ettik) çalışmıyor:

#include <stdio.h>                
#include <string.h>                
#include <stdlib.h>                

int main(void) {                 
     char p1[5];                
     char *p2[5];                
     char (*p3)[5];               

     strcpy(p1, "dead");              

     p2[0] = (char *) malloc(5 * sizeof(char));        
     strcpy(p2[0], "beef");             

     p3[0] = (char *) malloc(5 * sizeof(char));        
     strcpy(p3[0], "char");             

     printf("p1 = %s\np2[0] = %s\np3[0] = %s\n", p1, p2[0], p3[0]);   

     return 0;                
} 

birinci ve ikinci eserleri tamam ve ben ettik yaptıkları şeyi anladılar. Üçüncü deklarasyonun anlamı nedir ve onu kullanmanın doğru yolu nedir?

Teşekkür ederiz! İkinci char bir dizi 5 işaretçiler ise

+0

Kod çözme bildirimleri en az C ve C++ favori bölümümdür. –

cevap

12

üçüncü, 5 karakter dizisi için bir işaretçi olup.

şöyle düşünün:

________   _____________________ 
|0x7777| -------> | H | e | l | l | o | 
|______|   |_0_|_1_|_2_|_3_|_4_| 
    p   ^
        | 
        0x7777 

ikincisi benziyor Oysa:

"abc" "def" "ghi" "jkl" "mno" 
    ^ ^ ^ ^ ^
    |  |  |  |  | 
____________________________________ 
|0x9999|0x7777|0x3333|0x2222|0x6666| 
|___0__|___1__|___2__|___3__|___4__| 
        p 

Bu işaretçiler ve diziler arasındaki farkı anlamak önemlidir durumlarda biridir. Bir dizi, öğelerinin her birinin boyutunun sayımı olan bir nesnedir, oysa bir işaretçi yalnızca bir adrestir. İkinci durumda sizeof(p)5 * the_size_of_a_pointer verecektir. Üçüncü durumda, sizeof(p), hedef makineye bağlı olarak genellikle 4 veya 8 olan the_size_of_a_pointer'u verecektir.

+9

[Clockwise spiral rule] (http://c-faq.com/decl/spiral.anderson.html), C ile uğraştığınız zaman bilmeniz gereken kullanışlı bir şeydir. –

+0

5 karakterlik p3 ayırmayı ve p3'ü bunlara işaret etmeyi denedim ve işe yaramadı. Söylediğin gibi çalışmıyor ... Bazı örnek kodları veya daha net bir şeyi yayınlamayı düşünür müsün? – jpmelos

+0

Üçüncü durumda, sizeof (p3) dediğiniz şeyi vermez, makinemde bir işaretçinin boyutu olan 8 değerini verir. – jpmelos

4

Bu, bir dizi karakter için bir işaretçidir. C FAQ'da açıklanmıştır. Gelecekte, bir bildirimi anlamadığınızda, cdecl veya cdecl(1)'u kullanın.

+0

Çok teşekkür ederim, C SSS bağlantınız bu konuyu çok iyi anlamama yardımcı oldu. – jpmelos

3
char (*p3)[5]; 

aslında 5 char bir dizi için bir işaretçi bildirir. Bu, 5 char dizisine işaret eden bir işaretçiyi işaret etmesi gerektiği anlamına gelir. Hiçbir şeyden 5 tane ayırmaz, sadece bir işaretçi ve 5 char'a işaret eden bir şeye işaret etmelidir.

Yani, doğru kullanımıdır: bunu erişmek için p3 kullanarak o p1 dize Tek bir konumu erişmek istiyorsanız, örneğin, (*p3)[2] yapmalısınız

#include <stdio.h>                
#include <string.h>                
#include <stdlib.h>                

int main(void) {                 
     char p1[5];                
     char *p2[5];                
     char (*p3)[5];               

     strcpy(p1, "dead");              

     p2[0] = (char *) malloc(5 * sizeof(char));        
     strcpy(p2[0], "beef");             

     p3 = &p1;                

     printf("p1 = %s\np2[0] = %s\np3 = %s\n", p1, p2[0], *p3);    

     return 0;                
} 

. Üçüncü pozisyona erişecek. Bunun nedeni, ilk olarak p3'ü p1'e (konum aritmetiğini yapmadan önce (*p3) dereferences) dönüştürmeniz ve daha sonra bu adresin üçüncü konumuna (işaretsiz işaretçi tarafından işaretlenmiş) erişmenizdir.

+0

Harika, cevabımı daha iyi bir şekilde özetlediniz :-) –

4
char p[5];  // p is a 5-element array of char 
char *p[5];  // p is a 5-element array of pointer to char 
char (*p)[5]; // p is a pointer to a 5-element array of char 

C Bildirisi sözdizimi ifadeleri değil, nesnelerin türleri etrafında inşa edilmiştir.Fikir, beyan formunun, kodda görüneceği şekliyle ifade biçiminin eşleşmesidir. Yukarıdaki durumlarda dizilerle uğraşıyoruz. İlk durumda, p, char dizisidir; Belirli bir karakter değerine erişmek için, biz olur sadece diziye göstergesi:

val = p[i]; 

ifade p[i] tipi bu şekilde p beyanı char p[5] olup, char olup.

Sonraki durumda, p, char için bir dizi işaretçidir; diziye değeri, dizine erişmek ve sonuç KQUEUE: [] gibi

val = *p[i]; 

sonek operatörleri * gibi tekli operatörler daha yüksek bir önceliğe sahip, bu nedenle yukarıdaki

val = *(p[i]); 

olarak ayrıştırılır *p[i] ifadesinin türü char olup, p bildirimi char *p[5]'dur.

val = (*p)[i]; 

[] yüksek olduğundan: son durumda

, p bu nedenle sonuç olarak indis sonra dizi işaretçi KQUEUE sahip bir char değere erişmek ve, char bir dizi için bir gösterici unite *'dan daha öncelikli olarak, *'u p ( p[i]'un aksine) ile açıkça gruplandırmak için parantez kullanmamız gerekir. Yine, (*p)[i] ifadesinin türü char, dolayısıyla p bildirimi char (*p)[5]'dur. Dizilerin için

DÜZENLEME

İşaretçiler aşağıdaki bağlamlarda görüntülenebilir:

  1. Açıkça N boyutlu bir dizinin adresini alıyorsun:

    int x[10]; 
    int (*px)[10] = &x; 
    
    Not olduğu süre ifadeler x ve &x aynı değerini (dizinin ilk öğesinin adresi) değerini verir, farklı türleri vardır (int * vs int (*)[10]).

  2. dinamik bir dizi tipi nesne ayırmak konum

    :

    int x[10][20]; 
    foo(x); 
    ... 
    void foo(int (*px)[20]){...} 
    

: bir (N-1) -Boyut dizisine bir işaretçisi
int (*px)[10] = malloc(sizeof *px); 

  • Bir N-boyutlu bir dizi ekspresyon "azalır"

  • +0

    +1. Çok iyi bir açıklama! Teşekkürler, bildirimler hakkında nasıl düşünüleceğini açıklığa kavuşturdu! – jpmelos

    +0

    Düzenlemenizde, ilk bağlamda, 'x' türünün int *' olduğunu ve '& x' türünün int (*) [10]' türünde olduğunu söylersiniz. Yani aslında 'x' türü int var [10] ', sanırım? – jpmelos

    +1

    @jpmelos: "sizeof" veya "&" için bir işlenen olmadığından, x "int *' ye bozulur. –