2016-05-12 74 views
14

我有如下的結構:在運行時可以在結構中設置數組的大小嗎?

struct Query { 
    int  pages[]; 
    int  currentpage; 
}; 

我想知道是否可以創建結構之後設置該數組的大小。

Query new = malloc(sizeof(struct Query)); 

在此之後,我會進行一些計算,然後它會告訴我的大小pages[]必須這樣做。如果pages[]需要大小爲4,我該如何設置它?

+3

'int pages [];' - >'int * pages;'然後'malloc'-吃了它。請記住,在整個「免費」結構之前,頁面必須是免費的。 – LPs

+0

在其他語言中,您可以爲結構創建構造函數。不確定與c。但我認爲這是一條可以走的路。 –

+1

讓'pages'成爲一個int指針。這樣,您可以在創建結構後在malloc堆中爲它分配內存。 – nobism

回答

7

變化pages成員的類型指針。

struct Query { 
    int *pages; 
    int currentpage; 
}; 

struct Query *test = malloc(sizeof(struct Query)); 

if (test != NULL) 
{ 
    //your calculations 

    test->pages = malloc(result_of_your_calcs); 
    if (test->pages != NULL) 
    { 
     // YOUR STUFF 
    } 
    else 
    { 
     // ERROR 
    } 
} 
else 
{ 
    // ERROR 
} 

當你free你的結構,你必須做的是相反的。

free(test->pages); 
free(test); 
+1

我認爲你的意思是'if(test-> pages == NULL){/ * ERROR * /}',如果'test-> pages!= NULL不是錯誤的,' – cat

+1

是的。當然。我編輯過。 Tx @cat – LPs

14

在C99可以使用Flexible array members

struct Query { 
    int currentpage; 
    int pages[]; /* Must be the last member */ 
}; 

struct Query *new = malloc(sizeof(struct Query) + sizeof(int) * 4); 
+0

OP表示想要分配結構並在一些計算後分配數組。你應該添加一個'realloc'的例子。我個人認爲,BTW靈活陣列必須被「專家」人員使用。 – LPs

+0

@LPs,我認爲你是對的,但是用不同大小的realloc(比第一個'malloc')更加危險,不是嗎?對於這個具體情況,我認爲OP意味着在運行時不知道數組的大小來分配結構體(struct中只有一個「int」和一個數組,並且「int currentPage」可以存儲在一個臨時變量中'malloc'然後重新分配給'struct'),但我可能是錯的。請原諒我可憐的英語。 –

+1

我同意。這個特定的情況可以像你描述的那樣工作我不認爲'realloc'比使用'malloc'更危險。我的意思是:你必須知道你在使用靈活數組做什麼。 +1 – LPs

2

最好的解決辦法是使用指針int,而不是陣列。

你需要改變:

int pages[]; 

到:

int *pages; 

,然後動態地分配它像這樣:

Query *new = malloc(sizeof(struct Query)); 
if (new == NULL) 
    printf ("Error\n"); 
else 
{ 
    new->pages = malloc(4*sizeof(int)); 
    if (new->pages == NULL) 
     printf ("Error\n"); 
} 

否則,如果你想保持你的格式,你將使用C99 m頌。聲明pages爲你的結構的最後一個成員,是這樣的:

struct Query { 
    int currentpage; 
    int pages[]; 
}; 

然後執行:

Query *new = malloc(sizeof(struct Query) + 4*sizeof(int)); 
+0

不應該是'Query * new = ...'? – Shreevardhan

+0

@Shreevardhan是的,我錯過了星號!謝謝,我編輯了我的帖子:) – Marievi

+0

'new-> pages = malloc(4 * sizeof(int));'如果'new'的前一個'malloc'失敗,'會導致分段錯誤。 –

2

聲明它作爲指針,並使用malloc事後

struct Query { 
    int * pages; 
    int currentpage; 
}; 

. . . 

struct Query obj; 
obj.pages = malloc(n * sizeof(int)); // n is the length you want 
5

可以使用柔性陣列構件(在@AlterMann's answer詳情)(C99 +)或零長度陣列( GNU C)。

https://gcc.gnu.org/onlinedocs/gcc/Zero-Length.html引用,

零長度數組被允許在GNU C.他們是作爲一個結構的最後一個元素,那確實是一個可變長度對象的標題非常有用:

struct line { 
    int length; 
    char contents[0]; 
}; 

struct line *thisline = (struct line *) 
    malloc (sizeof (struct line) + this_length); 
thisline->length = this_length; 

對於標準的C90,鏈接的網站中提到

在ISO C90,你將不得不給contents長度爲1,這意味着要麼浪費空間要麼將參數複雜化爲malloc

這意味着要使代碼在標準C90/C89中工作,char contents[0];應該是char contents[1];

+0

GCC支持靈活的數組成員,因此沒有任何理由使用零大小的數組。而且你不需要製作惡意代碼 –

+0

是的。但靈活的陣列成員僅在C99 +中是標準的(是的,我知道C89是古老的,但值得一提)。至於演員陣容,我只是複製了鏈接網站的代碼(我知道不需要演員陣容) –

+0

@ M.M:在允許它們的某些實現中,零大小的數組比靈活的數組成員有一些優勢。例如,如果程序員注意到對齊,給定'struct SIZED_ARRAY {int size; int dat [0];}可以通過struct {SIZED_ARRAY arr;}創建一個初始化的實例。 int dat [4];} my_array = {{4},{1,2,3,4}};'。儘管一些C99編譯器提供了有用的擴展,但我不認爲C99本身提供了任何實用的擴展。 – supercat

相關問題