2017-06-15 162 views
4

所以我必須用C編寫一個vector式的數據結構,一般來說,我犯了這樣的結構:初始化C結構通過函數

struct Vector 
{ 
    int length; 
    int *elements; 
}; 

而且功能這樣的:

void initialize_vector(struct Vector* vector); 
void create_vector(struct Vector* vector, int* array, int n); 
void remove_vector(struct Vector* vector); 
void vector_add_element(struct Vector* vector, int element); 
void vector_insert(struct Vector* vector, int index, int element); 
void vector_remove_element(struct Vector* vector, int element); 
void vector_remove_at(struct Vector* vector, int index); 

現在,initialize_vector()函數,我想它只是初始化矢量屬性爲默認值(如length到0和*elements爲NULL)。我寫的是這樣的:

void initialize_vector(struct Vector* vector) 
{ 
    vector->elements = NULL; 
    vector->length = 0; 
} 

我想檢查是否正常工作,所以我寫了這段代碼:

#include <stdio.h> 
#include "vector.h" 


int main(int arc, char** argv) 
{ 
    struct Vector* vec; 
    initialize_vector(vec); 
    printf("%d\n", vec->length); 
    return 0; 
} 

我得到了著名Segmentation fault,所以我查了GDB,和當然,當一切都擰緊了這一行:vector->elements = NULL;

我不知道問題出在哪裏。我宣佈了一個矢量,我猜想它正確地傳遞給它,並且它弄得一團糟。我知道這可能是微不足道的,我會被一些超級計算機專家大大降低,但是,嘿,他沒有任何問題沒有任何問題。

+1

1:更改'結構矢量* VEC;'到'結構向量VEC;''initialize_vector(VEC);'到'initialize_vector(&vec);'將指針傳遞函數的結構 2:創建一個實例來一個帶有malloc()的Vector – Grifplex

+0

沒有爲'struct'分配內存 –

+0

「我聲明瞭一個向量」 - 不!你聲明並定義了一個**指針**給struct Vector,指針不是相同類型它指向詳細信息可在編程關鍵「當一切都搞砸了是這條線的那一刻......」 - !你搞砸了更早的編譯器警告是因爲好玩啓用他們,並留意 – Olaf

回答

10

你沒有聲明一個向量,你聲明瞭一個指針到一個向量。該指針未初始化,因此試圖取消引用它將調用undefined behavior

創建struct Vector,並通過其地址:

struct Vector vec; 
initialize_vector(&vec); 
printf("%d\n", vec.length); 

如果你想在同一時間分配的struct Vector空間,改變函數來調用malloc並返回指針:

struct Vector *initialize_vector() 
{ 
    struct Vector *vector = malloc(sizeof(*vector)); 
    if (!vector) { 
     perror("malloc failed"); 
     exit(1); 
    } 
    vector->elements = NULL; 
    vector->length = 0; 
    return vector; 
} 

... 

struct Vector *vector = initialize_vector(); 
+1

我有!!刪除我的答案。謝謝你幫助我理解。爲什麼對內存的引用丟失? –

+0

是的,確切地說,完美地工作,謝謝。方式,最好的方式來存儲它,創建一個向量,創建一個向量的指針並操作它的指針,或者把它保持爲一個常規向量,並且總是通過地址傳遞它? 或者按照@Coldspeed的建議,使用'mallloc()'來使它存在 – FrynioS

+1

@Coldspeed你正在修改一個局部變量。該功能以外的修改不可見。 – dbush

1

dbush給了一個很好的答案,所以我不會給你代碼。相反,我會給出一個C指針的解釋,以免再次遇到相同的錯誤。

struct Vector * vec;

聲明一個指向結構體的指針,而不是實際的結構體。什麼是指針?它是一個包含地址的變量。因此,所有指針,無論它們是int *,char *,char **還是struct Vector *,都具有相同的大小(通常取決於體系結構的32位或64位)。聲明指針的類型僅用於取消引用指針(獲取存儲在該內存地址中的數據)。這是有道理的,解除引用void *指針會導致錯誤。回到上面的語句中,這個聲明用英文表示爲:「vec是一個變量,可以保存結構向量的地址」。但是,現在vec並沒有一個有效的地址。

在爲指針變量賦值之前,存儲在該變量中的地址是垃圾,我們稱之爲未初始化的變量。在你的情況下,你然後將這個未初始化的地址傳遞給initialize_vector(),它嘗試訪問存儲在該地址中的值。但正如我們所知,這個地址是垃圾。這給了seg故障。

另一件需要指出的是,在編寫這些功能時,您需要做出設計決定。你是否想要struct Vectors存放在堆上(通過調用malloc)或堆棧上?堆允許更多的靈活性,但它也要求程序員仔細跟蹤正在使用的指針,以避免內存泄漏,這可能會變得棘手。如果我是你,我會從堆棧中的對象開始,然後將他們的地址傳遞給修改函數。 dbush的第一個答案。這樣你就不必擔心調用free()。

+0

是的,但後來我需要'malloc()',因爲實驗室的人告訴我們,我們的結構必須動態分配:D – FrynioS