2015-12-05 43 views
1

比方說,我有一個結構是作爲C中是否自動初始化malloc?

typedef struct mylist { 
    int head; 
    int tail; 
    int size; 
    buckets_t *bucketslots; 
} mylist_t; 

這樣的列表,然後

void create_list(mylist_t* list, int size) { 
    list->head = 0; 
    list->tail = 0; 
    list->size = size; 
    list->bucketslots = malloc(sizeof(bucket_t) * size); 
} 

現在,在我的主要方法,如果我執行:

mylist_t list1; 
create_list(&list1, 1000); 

請問倒數第二行自動malloc空間爲list1?或者,我是否需要明確malloc空間通過

malloc(sizeof(mylist_t)) 

我真的很想知道的是,如果這是一個有效的過程來製作一個mylist類型的結構並開始在main中使用它。

編輯

看來是c把列表1,當我宣佈倒數第二行中的堆棧,但它並不在堆中去。如果我想把它放在堆上,我應該做下面的事情嗎? :

mylist_t* create_list(int size) { 
    mylist_t list1 = malloc(sizeof(mylist_t)); 
    list->head = 0; 
    list->tail = 0; 
    list->size = size; 
    list->bucketslots = malloc(sizeof(bucket_t) * size); 
    return list1; 
} 

然後調用函數:

create_list(1000); 

有了這個,我會在整個程序訪問列表1?

+0

line mylist_t list1;'當在塊範圍內時,創建一個具有自動存儲持續時間的'mylist_t'類型的對象。有什麼不清楚的? – EOF

+0

「list1」的空間在您聲明時分配了!它不是一個需要分配內存的指針變量。 – skrtbhtngr

+0

對不起,我對C很新。當你說存儲時間時,你的意思是說內存中的空間是自動分配的嗎?這個空間是否等於sizeof(mylist_t)? –

回答

1

你提出替代爲create_list來分配和初始化一個結構幾乎正確的:

  • list1應該被定義爲一個指針mylist_t
  • 剷鬥指針分配應使用的大小指向bucket_t而不是結構的大小bucket_t,
  • 您還需要初始化桶指針數組。

下面是修改後的版本:

mylist_t *create_list(int size) { 
    mylist_t *list1 = malloc(sizeof(mylist_t)); 
    list->head = 0; 
    list->tail = 0; 
    list->size = size; 
    list->bucketslots = malloc(sizeof(bucket_t*) * size); 
    for (int i = 0; i < size; i++) 
     list->bucketslots[i] = NULL; 
    return list1; 
} 
3

C將從來沒有隱含malloc()任何東西。一般來說,無論何時你有這樣的問題,(直到你熟練掌握了這門語言,以便即使遇到這種問題也能夠停下來),請記住,C的哲學是永遠不要做任何背後的事情回來,永遠不要做任何你沒有明確要求的事情。

特別是甚至不是語言的一部分,比如內存分配。在C中,內存分配完全是運行時庫的問題。該語言沒有內存分配概念的內置知識。

+0

「除了你的背部之外,不要做任何事情」除非涉及到堆棧 –

+0

@Rhymoid像它對堆棧有什麼作用? –

+0

就像將局部變量和調用信息存儲在一個未定義的位置(背後,IMO)一樣,這會導致UB(例如堆棧溢出)。 –

4

當你寫

mylist_t list1; 
create_list(&list1, 1000); 

list1是在棧上分配的,該結構包含一個指針。 struct1中的成員不會被初始化。

create_list功能將分配空間的指針指向並初始化結構一般

堆總是需要使用malloc /釋放calloc明確分配。另一方面堆棧是自動的。

+0

@chqrlie好點,補充說。 –

+0

同時告訴OP有關「免費」堆分配結構的需求。他可能會認爲它們是自動回收的,就像在java中一樣。 – chqrlie

+0

所以,如果我想在堆上使用list1,我應該明確malloc。如果我要這樣做,我應該刪除「mylist_t list1;」這一行然後在create_list中添加malloc語句? –

1

第二行最後一行自動爲list1指定malloc空間嗎?

否。通常,通過爲節點分配空間,然後爲添加到列表的每個附加節點分配空間,創建列表。(無論該空間動態地或不分配)

create_list(&list1, 1000); 

list1mylist_t類型的節點)初始化headtailsize值,然後動態地分配buckets_t類型的陣列與size元件該節點。如果這是你的全部list1,那麼你的list1被分配。

0

兩件事情你需要了解。

  • 局部變量的作用域
  • 全局變量

在聲明中變量任何功能,甚至內鏈支架語句塊中,該變量有塊外沒有存在的代碼。您可以將其用作其他函數調用的參數,但如果您嘗試在它聲明的語句塊之外引用它,則它是錯誤的。這些是局部變量。

函數內聲明的變量是,該函數範圍內只有

全局變量。您可以聲明任何語句塊或函數的以外的變量。它是全局的,因爲同一個文件中的任何函數都可以引用該變量。

通常,編譯器會爲堆棧上的局部變量分配空間,儘管實際上局部變量可能保存在寄存器中,甚至永遠不會存儲在內存中。這些是我們留給編譯器解決的細節。

有時候人們會將「靜態」變量與「全局變量」混淆。靜態變量在聲明它們的文件之外不會按名稱「可見」。全局變量可以是可見的,但您也需要在頭文件中將它們聲明爲「extern」以允許這樣做。

在C語言中需要注意的一點是,在鏈括號語句塊中,您可以重用在塊之外聲明的變量名稱。在最接近你所在的層次上聲明的那個是優先的那個。

在C,這是非常有效的,下面所有的變量都不同

void myfunc(int n) 
{ 
    if(n == 1) 
    { 
     int n = 35 ; 

     /* This will print 35 */ 
     printf("n = %d\n", n) ; 
    } 
    else 
    { 
     int n = 45 ; 

     /* This n variable has a value of 45 */ 
     printf("n = %d\n", n) ; 
    } 

    /* but no matter what we did inside the if statements 
    * the n variable at this stage refers to the original one ! 
    * 
    * So this printf will show the original value. 
    */ 

    printf("n = %d\n", n) ; 
} 

我提到這一點,因爲越來越多的程序員開始在Java中,在那裏,這將是非法的(唉),並找到它令人困惑。這非常有用,特別是在宏中。