1. 程式人生 > >定義結構體與分配記憶體

定義結構體與分配記憶體

這幾天在學習資料結構的時候經常會出現一個問題,就是定義了節點的結構,然後定義了指向節點的指標,但是已經定義了指標為什麼就不能直接用呢,後來查了一下相關資料發現原來在新建指標的時候不會一同分配記憶體給他,所以會出現非常嚴重的錯誤。即為當宣告一個結構體指標時,為什麼還有new(C++)或者malloc()這種語句?

問題描述:
主題:定義結構體指標時,有沒有同時分配儲存空間定義結構體指標時,有沒有同時分配儲存空間啊?
看到結構體的陣列定義好以後就直接可以用了。但是結構體指標在連結串列中還要malloc()申請空間。這是為什麼啊?

主要針對的就是這兩個問題

下面來看一個例子

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

  struct data
{
    int i;
    int j;
};

int main(void)
{
    struct data dat1; //定義一個struct data型別的變數,和int i同理。
    printf("%d\n", sizeof(struct data)); //8個位元組
    printf("%d\n", sizeof(dat1));        //8個位元組

    struct data* pdat1;//定義一個struct data型別的指標,和int *pi 同理。
    printf("%d\n", sizeof(pdat1));        //4個位元組,就是一個指標的空間,pdat1並沒有結構體變數的資訊。

    pdat1 = (struct data*)malloc(sizeof(struct data)); //申請一個空間,把該空間地址給pdat1.
    printf("%d\n", sizeof(*pdat1));      //8個位元組

    struct data dats1[2]; 
    printf("%d\n", sizeof(dats1));     //16個位元組,兩個data變數,不是data指標。
    dats1[0].i = 20;  //可以直接使用數組裡面的結構體變數
    dats1[0].j = 30;
    
    struct data* dats2[2]; //指標陣列,包含兩個指標,而不是結構體變數
    printf("%d\n", sizeof(dats2));  //8個位元組,兩個指標的大小
    //dats2[0]->i = 20; //錯誤!還沒有給dats2[0] 指標分配空間
    //dats2[0]->i = 20; //錯誤!還沒有給dats2[0] 指標分配空間
    dats2[0] = (struct data*)malloc(sizeof(struct data)); //分配空間
    dats2[0]->i = 20; //ok
    dats2[0]->i = 20; //ok
    return 0;
}
這裡用gcc-32位編譯器。如果是64位編譯器則會出現不同。。這我還得研究下

執行的結果是這樣的

如果把註釋的兩句話刪去就會發現是錯誤的,原因就是沒有給指標分配記憶體;

如果把結構體改為

 struct data
{
    int i;
    int j;
    int x;
    int y;
};
相對應的執行結果是


從這兩個地方確實可以看得出來

結構體變數分配結構體本身大小的空間,結構體指標分配4個位元組,其實任何型別的指標都是分配四個位元組的指標空間。

#include <stdio.h>  
#include <stdlib.h>  
 
 struct data  
{  
    int i;  
    int j;  
	double x;
};  

int main()  
{  
	int a;
	int *aa;
	int a1[3];
	int *a11[3];

	double b;
	double *bb;
	double b1[3];
	double *b11[3];

	struct data p;
	struct data *pp;
	struct data p1[3];
	struct data *p11[3];


	printf("int:\t%d\n",sizeof(a));
	printf("*int:\t%d\n",sizeof(aa));
	printf("*int所指:\t%d\n",sizeof(*aa));	
	printf("int[3]:\t%d\n",sizeof(a1));
	printf("*int[3]:\t%d\n",sizeof(a11));
	printf("double:\t%d\n",sizeof(b));
	printf("*double:\t%d\n",sizeof(bb));
	printf("*double所指:\t%d\n",sizeof(*bb));
	printf("double[3]:\t%d\n",sizeof(b1));
	printf("*double[3]:\t%d\n",sizeof(b11));
	printf("data:\t%d\n",sizeof(p));
	printf("*data:\t%d\n",sizeof(pp));
	printf("*data所指:\t%d\n",sizeof(*pp));
	printf("data[3]:\t%d\n",sizeof(p1));
	printf("*data[3]:\t%d\n",sizeof(p11));

    printf("分配了記憶體空間\n");

	//*aa=1;
	//*bb=1;
	//pp->i=0;
	//pp->j=1;
	//pp->x=2;
	

	aa = (int*)malloc(sizeof(int)); //申請一個空間,把該空間地址給pdat1. 
  	printf("*intmalloc:\t%d\n",sizeof(*aa));
	bb = (double*)malloc(sizeof(double)); //申請一個空間,把該空間地址給pdat1. 
  	printf("*doublemalloc:\t%d\n",sizeof(*bb));
	pp = (struct data*)malloc(sizeof(struct data)); //申請一個空間,把該空間地址給pdat1. 
  	printf("*datamalloc:\t%d\n",sizeof(*pp));

	*aa=1;
	*bb=1;
	pp->i=0;
	pp->j=1;
	pp->x=2;
	getchar();
  
    return 0;  
}  
執行的結果是


雖然用malloc之前和之後兩者指向的記憶體空間大小是相同的,但是

定義指標的時候確實會分配,但是是隨機分配的,而且這個時候指標是不能使用的,因為你不知道分配的記憶體在哪,有沒有內容,起碼需要初始化下才能用。
        而malloc後指標會指向heap上的可用空間,這樣就算函式被回收,指標還是指向正確的內容,因為指標指向堆上的內容,如果沒有那一句malloc,程式會報錯uninitialized local variable 'p' used。

指標被宣告出來是會分配記憶體的,但是這塊記憶體是不能用的,你需要把指標初始化,或者用malloc在記憶體上宣告一塊可用的空間。具體到這個程式,就是先宣告一個指標型別的變數,然後給他在記憶體上分配一塊可用的空間。如果沒有malloc,編譯器會認為你沒有把指標初始化,也沒有給他分配可用空間,就會報錯