指針和結構體


結構體的認識

  • 結構體的定義
    將不同數據類型的數據對象組織在一起。
  • 結構體在c中和C++不同
    在C中的結構體只能自定義數據類型,結構體中不允許有函數,而C++中的結構體可以加入成員函數。C中的結構體只涉及到數據結構,而不涉及到算法,也就是說在C中數據結構和算法是分離的,而到C++中一類或者一個結構體可以包含函數(這個函數在C++我們通常中稱為成員函數),C++中的結構體和類體現了數據結構和算法的結合。

結構體的定義、初始化

  • 一般結構體
struct test//定義一個名為test的結構體 
{ 
 int a;//定義結構體成員a 
 int b;//定義結構體成員b 
}; 
test pn1;//定義結構體變量pn1 
test pn2;//定義結構體變量pn2 

pn2.a=10;//通過成員操作符.給結構體變量pn2中的成員a賦值 
pn2.b=3;//通過成員操作符.給結構體變量pn2中的成員b賦值 
test* point;//定義結構指針 
point=&pn2;//指針指向結構體變量pn2的內存地址

point->a=99;//通過結構指針修改結構體變量pn2成員a的值 

 

  • 含有指針
struct Student{   
        char *name;   
        int score;   
        struct Student* next;   
    };  
//重點記住,在結構體中含有指針需要為指針指定指向的內存地址
Student stu,*pStu;
//結構體成員需要初始化
stu.name = new char;//stu.name = (char*)malloc(sizeof(char));
strcpy(stu.name,"ddd");
stu.score = 99;
//結構體成員需要初始化
Pstu = new Student;//Pstu = malloc(sizeof(Student));
Pstu->name = new char//在用結構體指針的=時候先為整個結構體分配內存,然后再為結構體內部的指針申請內存。

//最后在根據那個地方new,然后進行delete
delete stu.name;
stu.name = null;
delete Pstu.name;
Pstu->name = null;
delete Pstu;
Pstu = null;
//記住最后一定將指針賦值為null,防止指針亂指,成為野指針。
View Code

 

  • 結構體嵌套
struct Data
{ 
int year;
int month;
int day;
}
struct stu /*定義結構體* / 
{ 
    char name[20]; 
    long num; 
    struct data birthday; /嵌*套的結構體類型成員*/ 
} ;

//結構體初始化
struct stu a;
a.name = "gaoqinag";//在聲明的時候自動在棧為數組進行內存分配
a.birthday.year = 2013;//對於嵌套的結構體同樣適用,自動 申請內存。
a.birthday.month = 12;
View Code

 

這樣的結構體,成員指針或者分配內存,或者指向常量區,不然它們就都是野指針;分配內存的話,就要釋放,分配內存的時候,是從外向里,即先分配結構體的指針,再分配成員指針,釋放的時候,是從里向外,先釋放成員指針,再釋放結構體指針,順序不能錯的。總之每個malloc都要對應一個free,每一個new要對應一個delete!

結構體數組

structdata/*定義結構體類型*/ 
{ 
     intday,month,year; 
};
structstu/*定義結構體類型*/ 
{ 
     char name[20]; 
     long num; 
     struct data birthday; 
};

main() 
{
     inti; 
     structstu*p,student[4]=
     {
         {"liying",1,1978,5,23},
         {"wangping",2,1979,3,14}, 
         {"libo",3,1980,5,6},
         {"xuyan",4,1980,4,21}
     }; 
/*定義結構體數組並初始化*/ 
     p=student;/*將數組的首地址賦值給指針p,p指向了一維數組student*/ 
     printf("\n1----Outputname,number,year,month,day\n"); 
     for(i=0;i<4;i++)/*采用指針法輸出數組元素的各成員*/ 
     printf("%20s%10ld%10d//%d//%d\n",(p+i)->name,(p+i)->num, 
     (p+i)->birthday.year,(p+i)->birthday.month, 
     (p+i)->birthday.day); 
}
View Code

 

結構體作為函數參數

  • #include<iostream>
    #include<string>
    using namespace std;
    //結構體定義
    struct Student{
     string name;
     int score; 
    };
    int main(){
     Student one;
     one.name="千手";
     one.score=99;
     // 值傳遞演示
     PrintByValue(one);//100
     cout<<one.name<<endl;
     cout<<one.score<<endl;//驗證 score的值是否加一了 //99
    //參數為指針演示
    Student *p=&one; 
     PrintByHand(p);//100
     cout<<one.name<<endl;
     cout<<one.score<<endl;//驗證 score的值是否加一了 //100
    //參數為引用演示
    PrintByQuote(one);//101
     cout<<one.name<<endl;
     cout<<one.score<<endl;//驗證 score的值是否加一了 //101
     return 0;
    }
    void PrintByValue(Student one){
     cout<<one.name<<endl;
     cout<<++one.score<<endl;//在Print函數中,對score進行加一 
    }
    void PrintByHand(Student *p){
     cout<<p->name<<endl;
     cout<<++p->score<<endl;//在Print函數中,對score進行加一 
    }
    
    void PrintByQuote(Student &one){
     cout<<one.name<<endl;
     cout<<++one.score<<endl;//在Print函數中,對score進行加一 
    }
    View Code

     

    參數為結構體值

這種方式值采取的“值傳遞”的方式,將結構體變量所占的內存單元的內存全部順序傳遞給形參。實際上在被調用函數,重新在棧中分配內存,將實參的值,進行賦值,在被調用函數操作時新申請內存的形參,和實參半點關系沒有。采用值傳遞的方式,如果在函數被執行期間改變了形參的值,該值不能反映到主調函數中的對應的實參,這往往不能滿足使用要求。因此一般較少使用這種方法。

  • 參數為指針

這種方式雖然也是值傳遞的方式,但是這次傳遞的值卻是指針。通過改變指針指向的結構體變量的值,可以間接改變實參的值。並且,在調用函數期間,僅僅建立了一個指針變量,大大的減小了系統的開銷。

  • 參數為引用

形參是對應的結構體類型的引用,虛實結合時傳遞的是地址,因而執行效率比較高。而且,與指針作為函數參數相比較,它看起來更加直觀易懂。因而,引用變量作為函數參數,它可以提高效率,而且保持程序良好的可讀性。

  • 引用傳遞

上面講解的是按值傳遞,按值傳遞就是將值傳遞進去,在函數中進行一些列操作,被調用函數中申請分配的內存不會傳出來。
引用傳遞最重要的目的就是將被調用函數申請的內存進行獲取,更准確將是內存的地址。
在這里講解一個重點就是在被調用函數申請內存的時候,怎樣從被調用函數這個傳出這個結構體,這里要從內存分析。
在被調用函數進行內存分配后需要將內存的地址獲取,而內存的地址往往是通過指針獲取,另一方面形參中創建一個指針后,要與實參的指針建立聯系。單純進行 stu* p = stu *ptr;這樣形參中對p進行操作和實參的*ptr半點關系沒有,所以傳入的二級指針。

void GetStu(Student** stu)
{
//這里做實驗,如果先申請內存,然后在賦值給stu,其實改變stu指向,不再指向實參了,內存還是沒有傳出去
    //Student *student = new Student;
//  student->name = "hahh";
//  student->score = 80;
//  stu = &student;
//這里直接獲取形參中指向,也就是實參地址,為實參地址分配內存
    *stu = new Student;
    (**stu).name = "ahha";//為實參中地址指向的內存賦值。
    (**stu).score = 80; 

}
Student *temp;//聲明一個結構體指針
*temp->name = "hah"//程序會報錯,沒有給結構體指針變量賦值呢。
GetStu(&temp);
cout<<(*temp).score<<endl;
cout<<(*temp).name<<endl;
cout<<temp->name<<endl;
delete temp;//記得釋放內存
View Code

 

版權聲明:本文為博主原創文章,未經博主允許不得轉載。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM