2015-02-22 26 views
7

C'ye 3D yapıları nasıl ayırır ve bildirirsiniz? İlk önce diziyi tahsis ediyor musunuz, yoksa ilan ediyor musunuz? İlk önce onu tahsis etmeniz gerektiğini düşünüyorum, böylelikle öbekte ilan edebilirsiniz, ancak daha sonra henüz yapılmamış bir şeyi nasıl ayıracaksınız? Ayrıca, hepsini bir kerede mi, yoksa elemente göre mi ayırmalısınız? Ayrıca yapıları diziye doğru yerleştiriyor muyum? nasıl yapılacağına ilişkin Benim tahminim olurdu:C içinde bir dizi yapı dizisi nasıl ayrılır ve bildirilir?

header.h

struct myStruct{ 
    int a; 
    int b; 
}; 
typedef struct myStruct myStruct_t; 

main.c

bunu farklı şekillerde bir çift vardır
#include "header.h" 
#include <stdio.h> 
#include <stdlib.h> 
int main(void){ 

    int length=2; 
    int height=3; 
    int width =4; 
    myStruct_t *elements; 
    struct myStruct arr = (*myStruct_t) calloc(length*height*width, sizeof(myStruct); 
    //zero based array 
    arr[length-1][height-1][width-1]; 

    int x=0; 
    while(x<length){ 
     int y=0; 
     while(y<height){ 
      int z=0; 
      while(z<depth){ 
       arr[x][y][z].a=rand(); 
       arr[x][y][z].b=rand(); 
       z++; 
      } 
      y++; 
     } 
     x++; 
    } 
    return 0; 
}  
+0

'.h' ve' .c' dosyalarının kullanımı hakkında konu dışı bildirim: http://stackoverflow.com/q/3482948/2186301 – yulian

cevap

1

, ne istediğine bağlı. Öncelikle, böyle (C99 ve bazı derleyici) yığın dizinizi ayırabilirsiniz: Eğer yığın tahsis istiyorsanız, o zaman uygun büyüklükte tek tahsisi yapabilir

myStruct_t arr[length][height][depth]; 

. Daha sonra endeks hesaplamayı kendiniz yapmak veya bir işaretçi yapmak (C99 ve bazı derleyiciler) sizin için işi yapabilir ya:

void *buf = malloc(length * height * width * sizeof(myStruct_t)); 
myStruct_t *arr = buf; 
myStruct_t (*arr2)[height][width] = buf; 

/* TODO: check return of malloc */ 
... 

arr[x * height * width + y * width + z].a = rand(); /* indexing the C89 way */ 
arr2[x][y][z].b = rand();       /* indexing the C99 way */ 

Ya elle birden fazla nitelik tahsis edebilirsiniz.

#include <stddef.h> 
#include <stdlib.h> 

typedef struct myStruct 
{ 
    int a, b; 

} myStruct_t; 

int main() 
{ 
    myStruct_t ***arr; 
    int length = 5000, height = 1000, depth = 20; 
    int x, y, z; 
    int ret = 1; 

    if (NULL == (arr = malloc(length * sizeof(myStruct_t**)))) 
    goto FAIL; 

    for (x = 0; x < length; ++x) 
    { 
    if (NULL == (arr[x] = malloc(height * sizeof(myStruct_t*)))) 
     goto FAIL_X; 

    for (y = 0; y < height; ++y) 
    { 
     if (NULL == (arr[x][y] = malloc(depth * sizeof(myStruct_t)))) 
     goto FAIL_Y; 

     for (z = 0; z < depth; ++z) 
     { 
     arr[x][y][z].a = rand(); 
     arr[x][y][z].b = rand(); 
     } 
    } 
    } 

    /* TODO: rest of program logic */ 

    /* program successfully completed */ 

    ret = 0; 

    /* reclaim arr */ 

FAIL_CLEANUP: /* label used by TODO code that fails */ 

    for (x = length - 1; x >= 0; --x) 
    { 
    for (y = height - 1; y >= 0; --y) 
    { 
     free(arr[x][y]); 
    FAIL_Y: 
     ; 
    } 

    free(arr[x]); 
    FAIL_X: 
    ; 
    } 

    free(arr); 

FAIL:  
    return ret; 
} 

Bu son sürümü, bellek yerellik kötüdür ve düzgün tahsis ve ıslah etmek önemli ölçüde daha karmaşıktır, içerdiği tüm açık noktalardaki çok daha fazla bellek kullanır. Bununla birlikte, boyutlarınız boyunca farklı boyutlara izin veriyor. Örneğin, arr[0][4] dizisi, buna ihtiyacınız varsa arr[0][7]'dan farklı bir boyuta sahip olabilir.

öbek üzerinde tahsis etmek istiyorsanız

, sonra muhtemelen tek tahsisi ve çok boyutlu işaretçi ile ikinci versiyonunu istiyorum (varsa) veya manuel olarak uygun matematik kullanarak indeksleme kendiniz yapın.

+0

Neden myStruct **? Neden iki yerine 3 *? i arr büyüklüğü ile tahsis istiyorsa, satır dizi = calloc şeklinde olur (uzunluk, boyutu (yapı *** arr)); ? – wolfclique

+1

arr, myStruct *** yapısı olarak bildirilmiştir. 3 * kullanır. Calloc/malloc çağıracağınız zaman, dönüş değeri, tahsis ettiğiniz türe karşılık bir tane daha indirmeye sahiptir. Örneğin, üst düzey calloc bir struct myStruct *** döndürür, çünkü bir dizi struct myStruct ** 'ı tahsis ettik. Eğer arr bir ifadesi üzerine sizeof kullandığınızda, geri yapı eklemeyin. Sadece sizeof söyleyebilirim (*** arr), sizeof (struct myStruct) eşdeğer olacağını. – jschultz410

+0

@ jschultz410 Bu malloc() 'ın her zaman sihirli bir şekilde çalıştığını düşünmüyorsunuz ve asla başarısız olmaz mı? Kodunuzun tanımlanmamış bir davranışı vardır, güvenli kod yazınız ve bunu öğretin. OP kodunuzu daha çok beğenirse, bu günlerden birinde uygulamalarından birini kullanacaksınız ve aniden çökecek ya da bir şeyler olacak. –

1

kolay bir yoludur:

myStruct_t (*arr2)[height][width] = calloc(length * sizeof *arr); 

Sonra döngü böyle devam arr2[x][y][z].a = rand(); erişebilir ve. Bu şekilde calloc, see here numaralı telefonu tanımıyorsanız. Malloc ile her zamanki gibi, devam etmeden önce arr2'u NULL'a karşı kontrol edin.

Üçlü işaretleme yaklaşımı gerçekten pratik bir çözüm değildir. Derleyiciniz değişken olarak değiştirilmiş türleri desteklemiyorsa, dizi 1-D'ye düzleştirilmelidir.

+1

@Forss'ın belirttiği gibi, değişken uzunluktaki diziler (ve buna benzer işaretçiler) maalesef C11'de isteğe bağlı bir özellik haline getirildi. – jschultz410

+0

@ jschultz410, uygun yerlerde kullanılmaması gerektiği anlamına gelmez. Güzel kod, tüm iyi derleyiciler üzerinde çalışabilir ve eğer C89 veya tembel-vendor-C11'de çalıştırılacaksa, çirkin bir seçenek kullanabilirsiniz (düzleme ve üçlü-işaretlemeyi tavsiye ederim) –

+0

Evet, tamamen katılıyorum. C11 standardının daha önce zorunlu olan bir kısmı (C99'da VLA'lar) şimdi isteğe bağlı yapması beni utandırıyor. Visual Studio *, Windows'da oldukça yaygın olarak kullanılmaktadır ve bu kod, AFAIK üzerinde derlenmeyecektir. – jschultz410