結構體指針


//////////////////////////////////////////////////////////////////////////結構體指針部分一////////////////////////////////////////////////////////////////////////

#include <stdio.h>
#include <stdlib.h>
int main()
{
struct student
{
int score;
char name[128]; //定義字符形式的數組。

};//注意結構體后面具有分號

struct student stu1;
stu1.score=90;
strcpy(stu1.name, "小明"); //因為name是數組,應當用strcpy進行賦值。如果是指針可以直接進行賦值。
printf("輸出學生的姓名成績:%s:%d\n",stu1.name,stu1.score);
struct student *p ;// 注意指針的運用是采用->的形式進行操作 ,此時是野指針
p=(struct student *)malloc(sizeof(struct student)); //對指針進行空間的開辟
p->score=98;
strcpy (p->name, "不知道"); //通過函數進行字符串的賦值
printf("輸出學生的名字,以及學生的成績:%s:%d\n",p->name,p->score); //結構體指針的使用采用的是箭頭
//注意結構體的指針,還可以直接的指向結構體的另一個對象
free(p);//實現對空間的釋放,方式空間的泄露
p= &stu1; //注意指向的是結構體對象的地址,應當進行取地址的操作,注意在進行指針的賦值的時候,使用的依舊是=號,不是箭頭。是指向某一個地址,並不是將地址給指針
printf("輸出學生的名字,以及學生的成績:%s:%d\n",p->name,p->score);//通過指針對結構體的對象stu1中的變量進行調用,注意是stu1對象操作后的結果
//此時結構體指針便是指向對象的地址,依然遵循指針的初衷
//研究結構體指針偏移量,從結果可以看出結構體指針偏移的量是整個結構之的大小。int+char[128]=132.
printf("打印偏移前的地址: %p\n",p);
p++;
printf("打印片偏移后的地址:%p\n",p);
return 0;
}

 ////////////////////////////////////////////////////////結構體指針部分二////////////////////////////////////////////////////////////////////////////////////

#include <stdio.h>
#include <stdlib.h>
struct student
{ int score;
char *name; // 注意此時是一個野指針,在使用的時候需要進行初始化。否則將會出現錯誤,非常的重要
};
struct student *initStuScore(int len) //定義一個返回值為strcut student 類型的函數。
{ struct student stu[5]; //創建五個對象,,也可以看成是對象的數組。
struct student *p=(struct student*)malloc(5*sizeof(struct student)); //開辟空間的大小。方式二;注意此處是形式變量,當程序執行以后就不存在,
int i;
for(i=0;i<len;i++) //通過對象的的總空間的大小,再除以空間的類型,求取i變量的范圍
{ p->name=(char *)malloc(128); //對指針對象中的指針進行空間的開辟,不能將其放在循環的外面進行空間的申請,
//在循環的外部進行空間的申請,只是對指針所指向的第一個地址的元素進行了初始化,
//那么當指針發生偏移的時候,將會出現結構體指針指向的指針,未進行空間的開辟,也就是野指針,出現錯誤
printf("請輸入學生的名字:\n");
scanf("%s",p->name); //對指針對象的指針進行賦值,此處是字符串,不用取地址,字符串表示地址
printf("請輸入學生的成績:\n");
scanf("%d",&(p->score)); //注意在進行給整形變量賦值的時候,應當進行取地址的方式
p++; //注意此時指針已經發生了偏轉,注意此時指針的偏轉是一個stu對象的空間大小,不是整個函數體
}
p=p-len; //通過這種的使用,對指針p的操作是正確的,可以正確的返回,注意函數返回的僅僅是局部變量的地址,並不是局部變量,局部變量將會消亡,因為是在堆中申請的內存空間
return p; //返回的僅僅是指針p的地址
}
struct student *findMax(struct student *p3 ,int len) //通過結構體的方式求出輸入放入成績的大小 ,注意,此時返回值是一個結構體的類型的指針,函數的形式參數也是一個結構體類型的指針
{struct student *Max; //定義結構體 ,該指針是局部的指針變量
int i;
Max=p3;// ,注意此時只是將結構體指針中的第一個地址給了結構體Max,注意指針的函數名就是指向第一個元素的地址
for(i=0;i<len;i++){
if(Max->score<p3->score){
Max=p3;
}
p3++; //指針的地址發生了偏移偏移的僅僅是局部的變量
}

return Max;

}
struct student *findmin(struct student *p4, int len) //注意形式參數一定要聲明參數的類型
{ struct student *min; //定義結構體指針
int i;
min=p4;// ,注意此時只是將結構體指針中的第一個地址給了結構體min,注意指針的函數名就是指向第一個元素的地址
for(i=0;i<len;i++){
if(min->score>p4->score){
min=p4;

}
p4++; //指針的地址發生了偏移

}
return min;

}
void printMsg(struct student *p1, int len ) //此時的返回值是空,但是形式參數是結構體類型的指針,此時將結構體可以看作是一種變量的類型
{ int i;
int j=sizeof(p1); // 通過結構體的方式定義的變量,此時這種方式求解的是指針地址所占大小
printf("%d\n",j);
int k=sizeof(p1[0]); //此時求解的是結構體的大小。也就是結構中所有類型變量的占空間中總和
printf("%d\n",k);
for(i=0;i<len;i++)// 在進行傳輸的參數指針,再次對其進行求解大小的時候,將會出現錯誤
// for(i=0;i<sizeof(p1)/sizeof(p1[0]);i++); //不能使用這樣的方式去求解指針的大小,這樣只是求解的指針在該環境下占的空間
{
printf("輸出學生的姓名以及分數:%s:%d\n",p1->name,p1->score);
p1++;
}
}

int findName(struct student *p5,char *name, int len){
int i;
for(i=0;i<len;i++){
if(strcmp(name,p5->name)==0){
// 注意: strcmp()函數其中具有兩個參數,用於比較字符串的大小:
//如果第一個字符串大於第二個字符串,則返回值為正數
//如果第一個字符串小於第二個字符串,則返回的是負數
//如果第一個字符串等於第二個字符串,則返回的是0.
return 1;
}
p5++; //事實上指針最初指想的地址為首地址,此處進行指針的偏移,便是對指針指向的地址進行偏移。
}
return -1;
}

int main()
{ int len; //注意此處定義的全局的變量,其他的的函數也可以使用
printf("請輸入總人數:");
scanf("%d",&len); //將輸入放入len變量的地址,之所以此處需要取地址,是因為將輸入的數字放入變量的地址中。
struct student *stu2 =initStuScore(len); //因為函數的返回值是結構體類型的指針
printMsg(stu2,len); //進行形式參數的傳遞,注意,在進行傳參的時候,指針將stu2 地址進行拷貝。
//在函數體中對其進行如何的操作,都不會影響stu2指針的結果
struct student *Max1= findMax(stu2,len); //及逆行返回值的接收。
printf("Max=%s:%d\n",Max1->name,Max1->score); //Max1依舊是一種結構體指針,通過->的方式對結構體中的變量進行調用
struct student *Min=findmin(stu2,len);
printf("%s:%d\n",Min->name,Min->score);

if(findName(stu2,"張琪",len)==-1)
{
printf("對不起。沒有找到此人!");
}
else
{
printf("恭喜你!找到啦");
}

/*
struct student stu[5]; //創建五個對象,,也可以看成是對象的數組。
//struct student *p=stu; //將指針指向對象的首地址,注意此時指針進行了初始化,所以不需要在進行空間的開辟等等 方式一:
struct student *p=(struct student*)malloc(5*sizeof(struct student)); //開辟空間的大小。方式二
int i;
for(i=0;i<sizeof(stu)/sizeof(stu[0]);i++) //通過對象的的總空間的大小,再除以空間的類型,求取i變量的范圍
{ p->name=(char *)malloc(128); //對指針對象中的指針進行空間的開辟,不能將其放在循環的外面進行空間的申請,
//在循環的外部進行空間的申請,只是對指針所指向的第一個地址的元素進行了初始化,
//那么當指針發生偏移的時候,將會出現結構體指針指向的指針,未進行空間的開辟,也就是野指針,出現錯誤
printf("請輸入學生的名字:\n");
scanf("%s",p->name); //對指針對象的指針進行賦值,此處是字符串,不用取地址,字符串表示地址
printf("請輸入學生的成績:\n");
scanf("%d",&(p->score)); //注意在進行給整形變量賦值的時候,應當進行取地址的方式
p++; //注意此時指針已經發生了偏轉,注意此時指針的偏轉是一個stu對象的空間大小,不是整個函數體
}
for(i=0;i<sizeof(stu)/sizeof(stu[0]);i++)
{p--;
printf("輸出學生的成績:\n");
printf("%s:%d\n",p->name,p->score);

}
*/
// 注意結構體指針依舊是一個指針,儲存的依舊是地址,注意結構以在創建對象的時候,可以理解是創建一種結構體類型的變量,初始化,用的是等號,加上大括號
//注意結構體指針的變量名的大小指針的指針地址的大小,指針的首地址的標志,p[0],值的是整個結構體的大小。
return 0;
}

//////////////////////////////////////////////////////////////////////////////////////////////////////結構體大小的計算//////////////////////////////////////////////////////////////////////////

#include <stdio.h>
#include <stdlib.h>
// 重點。重點 重點。
//1.結構體的偏移量必須是成員的大小的整數倍。
//2.結構體的大小必須是所有成員大小的整數被,(數組以及結構體除外,此處所說的結構體便是結構體中包含的結構體)
//滿足上面的方式雖然很浪費空間,但是可以按照計算機的規則進行訪問,這種對齊的方式加大了訪問的效率
struct s1
{ char ch1;
char ch2;
int n; //此處地址的大小是4,前面的兩個char之和為2,所以在偏移的時候,會自動的空出兩個空間,這樣前面的一共便是4,恰好是int是其整數倍
};
struct s2
{ char ca1; //1
int y; // 3+4
char ca2; //1

};
struct s3
{
char i;//1
int ca3; //4+3
char aa[12]; //10
};
struct s4
{
char i;
int ca4;
struct s{
char ch1;
char ch2;
int n;
};
float f;
};
struct s5
{
char ch5;
int i5;
union{
char ch;//注意:定義字符型的變量的時候,后邊不要帶數字
int ca5;
};

};
//#pragma pack(4) //指定的對齊的方式是4.雖然結構體中的最大占空間是8,注意此時的指定的對齊方是小於最大的占用空間。
struct s6
{
char ch6;
int i6;
float f;
double d; //所占的內存空間式8;
};
#pragma pack(10) //指定的對齊的方式是10.雖然結構體中的最大占空間是8,注意此時的指定的對齊方是小於最大的占用空間。,其后面的全部受其進行控制。
struct s7
{
char ch7;
int i7;
float f;
double d; //所占的內存空間式8;
};

int main()
{ printf("s1=%d\n",sizeof(struct s1)); //輸出的結果是8,注意在進行計算結構體的時候,應當帶上struct,結構體的標志
printf("s2=%d\n",sizeof(struct s2)); //此時輸出的結果是12,但是我們邏輯分析結構體的大小是9,但是為了滿足結構體的大小是所有成員的整數倍,所以結構體制動生成的到大小為12
printf("s3=%d\n",sizeof(struct s3));//輸出的結果為20,滿足前面兩個數的整數倍,但是不滿足數組,也就是說,結構體的大小,不需要是數組的整數倍
printf("s4=%d\n",sizeof(struct s4));//此時輸出的大小是20,明顯不是里面所包含的結構體大小8的整數倍,所以當結構體中,定義了結構體是,其所包含的結構體只能看做式 int 或者char等類型,不能看作式一個整體
printf("s5=%d\n",sizeof(struct s5));// 此時輸出的結果式12,
printf("s6=%d\n",sizeof(struct s6));//注意此處輸出的結果是20,如果以8為對齊的方式,那么因該是24,所以此處的對齊的方式是4.
printf("s7=%d\n",sizeof(struct s7)); //注意此時輸出的結果不是30,而是24,不是按照規定的對齊方式。因為此處規定的對齊大於結構體的中最大的空間占用。那么此時便是以結構體中的最大的空間占用作為對齊的方式。。
//重點。
return 0;
}

 /////////////////////////////////////////////////////////////////////////////////////////////指針變量空間的申請//////////////////////////////////////////////////////

#include <stdio.h>
#include <stdlib.h>
int main()
{ //int a[3];
int *a=(int*)malloc(3*sizeof(int));
int i;
for(i=0;i<3;i++){
a[i]=i;// 此處是將指針。
}
for(i=0;i<3;i++){

printf("通過數組的變量名打印對數組進行遍歷:%d\n",a[i]);

}
int n;
printf("請輸入需要輸入放入申請int的空間大小的個數");
scanf("%d",&n);
int arry[n];// 通過輸入值,開辟數組空間的大小
//int *arry= (int*)malloc(n*sizeof(int)); //此處是申請空間,通過malloc的方法。此處進行了強制的轉換(int*)
printf("打印n的值:%d\n",n);
if(arry==NULL){
printf("空間內存申請失敗");
}

printf("請輸入學生的成績:\n");
for(i=0;i<n;i++){
scanf("%d",&arry[i]);// 此處將變量i的值,依次的存放在數組這之中,在通過scanf()在輸入的時候具有嚴格的格式,不要在里面輸入其他任何的東西。否則將會引起不必要的錯誤
printf("打印i的值:%d\n",i);


}
for(i=0;i<n;i++){
//printf("通過指針的方式訪問元素指針的元素: %d\n",*arry++);
printf("通過數組的方式,訪問數組中的元素:%d\n",arry[i]);
}

//printf("通過指針的方式訪問元素指針的元素: %d\n",*arry++);

return 0;
}
/*
內存泄漏的問題。
while(1)
{


sleep(1);
int *p=(int*)malloc(1024);// 注意在LinuX系統同只有程序執行完畢以后才會將空間的內存進行釋放,程序沒有執行結束空間的內存將不會釋放,可能出現死機的現象
//通常采用free()函數及逆行合理的空間及逆行釋放
//避免的方法
free(p);// 注意此時的指針式野指針,指向的地址是由系統隨機進行分配的
p=NULL;//此時p指針便不再是野指針。
// 通常指針初始化便是這樣 int *p=NULL;

}
*/

 


免責聲明!

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



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