2011-12-12 51 views
2

我知道如何創建可用於訪問的陣列的結構,例如數組:使用結構訪問用C

#include <stdio.h> 

typedef struct { 
    int i; 
    int j; 
    int k; 
} MyStruct; 

int main() 
{ 
    MyStruct *ms; 
    int array[9]; 
    int i; 

    for(i=0;i<9;++i) array[i] = i; 

    ms = (MyStruct *)array; 

    for(i=0;i<3;++i) printf("%d %d %d %d\n",i,ms[i].i,ms[i].j,ms[i].k); 
    return 0; 
} 

,讓我訪問數組[0]作爲MS [1] .i和數組[1]爲ms [1] .j等等。但是,如果我想在運行時已知的結構中使用數組,但是在編譯時卻不能使用數組,我該如何做同樣的事情?喜歡的東西:

#include <stdio.h> 

typedef struct { 
    int *myArgs; 
} MyStruct; 

int main() 
{ 
    MyStruct *ms; 
    int array[9]; 
    int i; 

    for(i=0;i<9;++i) array[i] = i; 

    ms = (MyStruct *)array; 

    for(i=0;i<3;++i) printf("%d %d %d %d\n",i,ms[i].myArgs[0],ms[i].myArgs[1],ms[i].myArgs[2]); 
    return 0; 
} 

這在這個例子中,我想知道在運行時myArgs的長度是3。但它也可以myArgs是長度爲9,在這種情況下,MS應該是長度爲1

編輯:

我正在爲一個PDE求解器存儲一個解決方案集,這個求解器有一些在編譯時固定的知識,然後有一些未知數的額外參數。例如,我的數組將有X,Y,Z,但之後它可能會有3或5或10個以上的東西。因此,我想提供一種結構,以便稍後訪問字段以便於閱讀,例如solution.x,solution.y,solution.z,solution.chemicalSpecies [0],solution.chemicalSpecies [1]等。在編譯時,物種的數量完全未知。

我使用一個外部庫,將未知數的數量作爲一個數組存儲,並且我可以以[k] [j] [i] [numUnknowns]的形式返回數組,並且很好給訪問像解決方案[k] [j] [i] .something。

+1

只是出於好奇,你爲什麼要這樣做在真實的代碼? –

+1

這都不是有效的;這都是未定義的行爲。 –

+0

這個問題需要澄清。如果數組是來自某種外部設備的緩衝區,並且在其上覆蓋了一系列結構,則可能需要這樣做。 – Fred

回答

1

號在你的第一種情況下,你的結構的尺寸是3個int變量的大小。當你將數組的指針指向結構的指針時,每個元素將與一個MyStruct元素相匹配,代碼中的魔術是什麼(理論上這是不可移植的)。

在第二種情況下,結構的大小是指向int的1個指針的大小。你必須意識到指針與數組在使用方面有一些相似之處,但它們並不是一回事。指針只是一個具有指向內存地址的單個值的變量。該地址的內容可以用作數組。

在C語言中,結構體和數組的大小是在編譯時處理的,所以struct的大小在運行時不能改變,因爲它的指針大小也是固定的,所以它不會在你的結構體中有一個指針。

也許一個很好的解決你會使用一個抽象數據類型,如:

typedef struct { 
    int m; /* number of lines */ 
    int n; /* number of columns */ 
    int *data; /* pointer to the actual data */ 
} Matrix; 

然後,你可以使用結構創建輔助功能:

void matrix_new(Matrix *m, int rows, int columns); 
int matrix_get(Matrix *m, int i, int j); 
void matrix_set(Matrix *m, int i, int j, int value); 
void matrix_free(Matix *m); 

如果太笨拙的,你甚至可以使用混合的方法(不是太抽象的類型):

int matrix_get(Matrix *m, int i, int j) 
{ 
    return m->data[i * m->n + j]; 
} 

int main() 
{ 
    Matrix m; 
    int array[9]; 
    int i; 

    for(i=0;i<9;++i) array[i] = i; 

    m.m = m.n = 3; 
    m.data = array; 

    for(i=0;i<3;++i) 
    printf("%d %d %d %d\n", i, 
          matrix_get(&m, i, 0), 
          matrix_get(&m, i, 1), 
          matrix_get(&m, i, 2)); 
    return 0; 
} 
1

一般來說,給定的數組大小NmyArgs < N,您將有N/myArgs完整的數據集,其餘N%myArgs項。你可以基於你的數組索引。

但是,這段代碼看起來像一個維護夢魘。你想達到什麼目的?可能有更好的方法。

+0

我願意提供更好的方式提供方便的訪問建議。與我合作的每個人都來自fortran背景,因此使其易於理解/使用該庫是至關重要的。即使這意味着我需要在後端進行更多維護。 – tpg2114

0

給定你的澄清,我會去解決這個問題如下。我有一個結構既有固定的x,y和z,又有一個指向數組的指針,您可以將它設置爲解數組中相應點的位置。事情是這樣的:

struct MyStruct { 
    int x, y, z; 
    int *extras; 
}; 

... 
int solutions[9]; 
struct MyStruct ms; 
ms.x = solutions[0]; 
ms.y = solutions[1]; 
ms.z = solutions[2]; 
ms.extras = (solutions + 3); 
... 

這樣一來,您就可以輕鬆訪問您需要的領域,像演員:

ms.extras[0] 

至少應該工作,把我的頭頂部。

如果我是你,我也會在num_extras中加入數據,這樣你就不會跑到數組的末尾。

編輯:如果你正在尋找讓他們被鏡像,你可以改爲做:

struct MyStruct { 
    int *x, *y, *z; 
    int *extras; 
}; 

然後有:

... 
int solutions[9]; 
struct MyStruct ms; 
ms.x = &solutions[0]; 
ms.y = &solutions[1]; 
ms.z = &solutions[2]; 
ms.extras = (solutions + 3); 
... 

但是,這是很多喜歡你有什麼之前不是嗎?

+0

雖然不會重複數據嗎?它既可以在原始數組中,也可以在結構中,因此對ms.x所做的更改不會反映在解決方案[0]中,反之亦然。 – tpg2114

+0

我相應地爲我的答案添加了更新。 –