簡體   English   中英

malloc的以下代碼行是什么?

[英]What the following line of code with malloc does?

我有以下實現來鏡像二叉樹。

#include<stdio.h>
#include<stdlib.h>

/* A binary tree node has data, pointer to left child
   and a pointer to right child */
struct node
{
    int data;
    struct node* left;
    struct node* right;
};

/* Helper function that allocates a new node with the
   given data and NULL left and right pointers. */
struct node* newNode(int data)

{
  struct node* node = (struct node*)
                       malloc(sizeof(struct node));
  node->data = data;
  node->left = NULL;
  node->right = NULL;

  return(node);
}


/* Change a tree so that the roles of the  left and
    right pointers are swapped at every node.

 So the tree...
       4
      / \
     2   5
    / \
   1   3

 is changed to...
       4
      / \
     5   2
        / \
       3   1
*/
void mirror(struct node* node)
{
  if (node==NULL)
    return; 
  else
  {
    struct node* temp;

    /* do the subtrees */
    mirror(node->left);
    mirror(node->right);

    /* swap the pointers in this node */
    temp        = node->left;
    node->left  = node->right;
    node->right = temp;
  }
}


/* Helper function to test mirror(). Given a binary
   search tree, print out its data elements in
   increasing sorted order.*/
void inOrder(struct node* node)
{
  if (node == NULL)
    return;

  inOrder(node->left);
  printf("%d ", node->data);

  inOrder(node->right);
} 


/* Driver program to test mirror() */
int main()
{
  struct node *root = newNode(1);
  root->left        = newNode(2);
  root->right       = newNode(3);
  root->left->left  = newNode(4);
  root->left->right = newNode(5);

  /* Print inorder traversal of the input tree */
  printf("\n Inorder traversal of the constructed tree is \n");
  inOrder(root);

  /* Convert tree to its mirror */
  mirror(root);

  /* Print inorder traversal of the mirror tree */
  printf("\n Inorder traversal of the mirror tree is \n"); 
  inOrder(root);

  getchar();
  return 0; 
}

我說的是以下幾行:

  struct node* node = (struct node*)
                       malloc(sizeof(struct node));

我有c / c ++的中級知識,但我非常害怕指針。 即使經過幾次嘗試,我也無法獲得指針。 我盡可能地避免它們,但是當實現像樹這樣的數據結構時,沒有其他選擇。 為什么我們在這里使用malloc和sizeof? 另外我們為什么要進行構建(struct node *)?

首先在C中使用malloc時進行轉換是沒有必要的。 (見這里

您正在進行mallocing,因為您正在分配節點結構大小的堆內存。 你在C中看到,你必須記住所有變量的存儲位置。 stackheap (見這里

在函數內部,您的變量稱為局部變量 ,存儲在stack 離開函數后,清除堆棧中的變量。

為了能夠在函數之外引用或使用局部變量,你必須在heap分配內存,這就是你在這里所做的。 您正在堆中分配內存,以便您也可以在其他函數中重用相同的變量。

綜上所述:

  • 函數內的變量是函數局部變量 ,因此稱為局部變量
  • 對於訪問局部變量的其他函數 ,您必須在堆中分配內存以與其他函數共享該變量。

為了舉例說明原因,請考慮以下代碼:

#include <stdio.h>
#include <string.h>

char *some_string_func()
{
    char some_str[13]; /* 12 chars (for "Hello World!") + 1 null '\0' char */

    strcpy(some_str, "Hello World!");

    return some_str;
}

int main()
{
    printf("%s\n", some_string_func());
    return 0;
}

它非常簡單, main是簡單地調用一個函數some_str_func ,它返回一個局部變量some_str ,編譯上面的代碼會起作用,但不是沒有警告:

test.c: In function ‘some_string_func’:
test.c:11:9: warning: function returns address of local variable [enabled by default]

雖然它編譯注意some_strsome_str_func()是(在函數的棧IE) 返回一個局部變量的函數。 由於一旦你離開函數some_str_func()就清除了堆棧,在main() ,就不可能獲得some_str的內容,即“Hello World”。

如果你試圖運行它,你得到:

$ gcc test.c
$ ./a.out

$

它什么都不打印,因為它無法訪問some_str 為了解決這個問題,你可以為字符串“Hello World”分配一些內存空間。 像這樣:

#include <stdio.h>
#include <string.h>

char *some_string_func()
{
    char *some_str;

    /* allocate 12 chars (for "Hello World!") + 1 null '\0' char */
    some_str = calloc(13, sizeof(char));

    strcpy(some_str, "Hello World!");

    return some_str;
}

int main()
{
    char *str = some_string_func();
    printf("%s\n", str);

    free(str);  /* remember to free the allocated memory */
    return 0;
}

現在,當您編譯並運行它時,您會得到:

$ gcc test.c
$ ./a.out
Hello World!
$

如果你很難理解C,我知道很多人發現Brian W. Kernighan和Dennis Ritchie的“C編程語言”是一個非常好的參考,但更現代和圖形化(甚至有趣的閱讀!認真)的書是Head First C David和Dawn Griffiths解釋了許多重要的C概念,例如Heap和Stack,動態和靜態C庫之間的區別,為什么使用Makefiles是一個好主意,Make如何工作,以及之前沒有解釋的更多概念常見的C書,絕對值得一看。

另一個很好的在線資源是Zed Shaws Learn C the Hard方式 ,他提供了很好的代碼示例和注釋。

閱讀: void *malloc(size_t size);

malloc()函數分配size字節並返回指向已分配內存的指針。 內存未初始化。 如果size為0,那么malloc()將返回NULL或一個以后可以成功傳遞給free()的唯一指針值。

因此,在

struct node* node = (struct node*)malloc(sizeof(struct node));
  //                                     ^----size---------^

你正在分配size = sizeof naode字節的內存塊和從存儲在node指針中的malloc返回的地址。

注意您有錯誤的變量名稱不應該是node因為它是結構名稱。 您可以! 但不是很好的做法。 此外,如果類型被更改, sizeof(*pointer)優先於sizeof(Type)

附注:避免不通過malloc和calloc函數轉換返回地址是安全的。 閱讀: 我是否施放了malloc的結果?

所以 正確 上述聲明的優選形式是:

struct node* nd = malloc(sizeof *nd);
  //                     ^----size-^

兩個糾正:(1)刪除類型轉換和(2)將變量名稱更改為nd

使用sizeof -

sizeofT )將告訴存儲類型為T的變量所需的字節數

使用malloc -

Malloc動態分配內存,即在運行時(當程序實際由CPU及其內存執行時)。 當我們不確定運行時所需的內存量時,我們主要使用它。 所以我們使用malloc在運行時動態分配它。

使用( struct node* ) -

Malloc返回一個指向內存塊的指針,其中包含您要求的空間量(在其參數中)。 這個空間只是內存中的一些空間。 因此,該指針沒有與之關聯的類型。 我們將這個指針轉換為( struct node* ),因為它會讓機器知道類型( struct node )的變量將保存在這個內存中。

void* malloc (size_t size);

分配內存塊

分配大小字節的內存塊,返回指向塊開頭的指針。 新分配的內存塊的內容未初始化,保留不確定的值。 如果size為零,則返回值取決於特定的庫實現(它可能是也可能不是空指針),但返回的指針不應被解除引用。

並且不要轉換malloc的結果。

你還需要釋放這個記憶:

void free (void* ptr);

釋放內存塊

先前通過調用malloc,calloc或realloc分配的內存塊被釋放,使其再次可用於進一步分配。

你使用malloc通常讓指針有東西指向。

指針就像一個街道地址,站在地址上的建築物是由malloc構建的 - 或者至少是構建建築物所需的大小 - 你在那里建造的東西取決於你。

在您的示例中,樹中的每個節點都是使用malloc分配的字節數,節點的大小是保存節點所有內容所需的字節數。

二叉樹將使用malloc分配它的每個節點,在內存中是無關緊要的,並且可能是用malloc和指針理解有點棘手的東西。 只要有指向這些位置的指針一切都很好。

struct node* node = (struct node*)malloc(sizeof(struct node)); 

占用足夠的空間來容納node結構

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM