程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> C語言 >> 關於C語言 >> 總結了一些指針易出錯的常見問題(四),指針常見問題

總結了一些指針易出錯的常見問題(四),指針常見問題

編輯:關於C語言

總結了一些指針易出錯的常見問題(四),指針常見問題


指針與結構體

  簡介:我們可以使用C的結構體來表示數據結構元素,比如鏈表或樹的節點,指針是把這些元素聯系到一起的紐帶。

typedef struct _person{
    char* firstName;
    char* lastName;
    char* title;
    unsigned int age;
} Person;
/*用點表示法初始化*/

Person person;
person.firstName=(char*)malloc(strlen("Emily")+1);
stcpy(person.firstName,"Emily");
person.age=23;

/*****結構體指針初始化*/
Person *ptrperson;
ptrperson=(Person*)malloc(sizeof(Person));
ptrperson->firstName=(char*)malloc(strlen("Emily")+1);
strcpy(ptrperson->firstName,"Emily");
ptrperson->age=23;  // (*ptrperson).age = 23;

為結構體分配內存,分配的內存大小至少是各個字段的長度之和。不過,實際長度會大於這個和,結構體的各字段之間可能會有填充。結構體數組各元素之間會有填充。

結構體釋放問題:

 用結構體變量和指向結構體的指針函數參數

  1.用結構體變量的成員作參數。(用法和普通變量相同)

  2.用結構體變量作實參。形參也必須是同類型的結構體變量。調用期間形參也要占用內存。(空間和時間上開銷較大),較少使用該方法。

  3.用指向結構體變量(或數組)的指針作實參,將結構體變量(數組)的地址傳給形參。

用指針處理鏈表

  鏈表是一種動態地進行存儲分配的一種數據結構。 鏈表是C語言編程中常用的數據結構,比如我們要建一個整數鏈表,一般可能這麼定義:

struct int_node {
        int val;
        struct int_node *next;
};

  假設有五個學生某一門功課的成績分別為A、B、C、D和E,這五個數據在內存中的存儲單元地址分別為1248、1488、1366、1022和1520,其鏈表結構如圖所示。

         

  鏈表有一個“頭指針”變量,圖中以 head表示,它存放一個地址,該地址指向鏈表中第一個結點,第一個結點又指向第二個結點……直到最後一個結點。該結點不再指向其他結點,它稱為“表尾”,它的地址部分存放一個“NULL”(表示“空地址”),鏈表到此結束。鏈表中每個結點都包括兩個部分:用戶需要用的實際數據和下一個結點的地址。

  鏈表每個結點中只有一個指向後繼結點的指針,該鏈表稱為單鏈表。其實結點中可以有不止一個用於鏈接其他結點的指針。如果每個結點中有兩個用於鏈接其他結點的指針,一個指向前趨結點(稱前趨指針),另一個指向後繼結點(稱後繼指針),則構成雙向鏈表。雙向鏈表如圖所示。

        

/*單鏈表的例子(靜態鏈表:因為所有節點在程序中定義的,不是臨時開辟的,也不能用完後釋放)*/
#include<stdio.h>
//#define NULL 0

 struct student
 {
     int num;
     int score;
     struct student *Next;
 };
     int main()
     {
         struct student a,b,*head,*p;
         a.num=10012; a.score=99;
         b.num=10013; b.score=81;
         head=&a;
         a.Next=&b;
         b.Next=NULL;
         p=head;
         do
         {
             printf("%5d  %ld\n",p->num,p->score);
             p=p->Next;
         }while(p!=NULL);
     }

  問題:結構體的變量名可以當做地址賦給指針嗎?沒有頭指針head行不行?p起了什麼作用?沒它可以嗎?

處理動態鏈表用到的函數  calloc/malloc/free

  malloc函數原型:  void *malloc(unsigned int size);其作用是在內存的動態存儲區分配一個長度為size的連續空間。此函數的值(返回值)是一個分配域的起始地址(void類型);若函數未成功執行,則返回空指針(NULL)。

  calloc函數原型:  void *calloc(unsigned n,unsigned size);其作用是在內存的動態存儲區分配n個長度為size的連續空間。函數返回一個指向分配域起始位置的指針;否則,返回NULL。

  free  函數原型:  void free(void *p);釋放由p指向的動態存儲區。free無返回值。

建立動態鏈表(知難而進)

/*寫一函數建立一個有3名學生數據的單向動態鏈表*/
 #include<stdio.h>
 #include<malloc.h>
 //#define NULL 0
 #define LEN sizeof(struct student)
 
 struct student
 {
     long num;
     float score;
     struct student *next;
  };
  int n;
  struct student *creat(void)
  {
      struct student *head;
      struct student *p1,*p2;
      n=0;
      p1=p2=(struct student*)malloc(LEN);
      scanf("%ld,%f",&p1->num,&p1->score);
      head=NULL;
      while(p1->num!=0)
      {
          n=n+1;
          if(n==1) head=p1;
          else
          p2->next=p1;
          p2=p1;
          p1=(struct student*)malloc(LEN);
          scanf("%ld,%f",&p1->num,&p1->score);
       } 
       p2->next=NULL;
       return(head);
  }
 
 int main()
 {
     creat();
 }

建立鏈表首先要定義一個包含數據域和指針域的的結構類型,然後建立指向表頭節點的頭指針head,最後通過malloc函數動態申請一塊內存作為表頭節點。

typedef struct node  
{  
int data; /*信息*/  
struct node *link; /*指針*/  
}NODE; /*定義節點*/  
NODE *head; /*定義頭指針head */

定義結構類型和頭節點之後,我們要建立不包含數據的表頭節點,可以按下列語句進行操作。

NODE *p; /*說明一個指向節點的指針變量p */  
p=(NODE*) malloc(sizeof(NODE)); /*申請表頭節點*/  
p->link = NULL; /*將表頭節點的link置為NULL */  
head=p; /*head指向表頭節點p*/ 

由於此時鏈表中只有一個表頭節點,沒有數據節點,所以稱為空鏈表。

p=(NODE*) malloc(sizeof(NODE)); /*申請一個數據節點*/  為了在鏈表中保存數據,可以從表頭位置將數據節點插入到鏈表中,例如,插入一個數據節點:

p=(NODE*) malloc(sizeof(NODE)); /*申請一個數據節點*/  
gets(p ->data); /*輸入一個新的數據*/  
p->link=head->link; /*建立鏈接關系。將表頭節點的link存入p 的link中*/  
head->link=p; /*將數據節點插在表頭節點之後成為第一個數據節點*/ 

插入第一個數據節點後鏈表,然後繼續插入下一個數據節點。

create(NODE *head,int n)  根據上面的鏈表建立過程,可以寫出函數create建立有n個數據節點的鏈表。

create(NODE *head,int n)  
{  
NODE *p;  
for(; n>0;n--)  
{  
p=(NODE*) malloc(sizeof(NODE));  
if(p==NULL)  
exit(0);  
gets(p->data);  
p->link = head->link;  
head->link = p;  
}  
} 

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved