(四)結構體、共用體、枚舉、位元組對齊

來源:互聯網
上載者:User
一、結構體
1、概念:
結構體是複合的資料類型,是不同類型 資料的集合
在C語言中沒有具體的結構體類型,但是C語言給出了定義結構體類型的文法格式,所以結構體也成為自訂類型
2、結構體類型定義的文法格式
struct  <結構體標籤>{
成員類型  成員名;
成員類型  成員名;
....    ....
成員類型  成員名;
};
例如:定義一個學生的類型
struct student{
int sno;
char name[20];
int age;
float score;
};
3、結構體變數的定義
1》常規定義:
struct student{
int sno;
char name[20];
int age;
float score;
};
struct student  st1;  //st1為結構體變數
2》與類型同時定義
struct student{
int sno;
char name[20];
int age;
float score;
}st2; /st2為結構體變數
3》直接定義
struct {
int sno;
char name[20];
int age;
float score;
}st3; /st3為結構體變數
4、結構體變數的初始化
1》完全初始化

按順序給結構體中的每個成員賦值,例如

struct student  st1 = {1001,"張飛",25,98.1}; 
2》部分初始化

按順序給結構體中的前若干個成員賦值,例如:

struct student  st2 = {1001,"張飛"};  //st2為結構體變數
3》指定成員初始化
不按順序給結構體中某一些成員賦值,例如:

struct student  st3 = {.name="張飛",25,.sno = 1002};  //st2為結構體變數
5、結構體變數的使用:
1》賦值:
除了初始化之外,不能像 .name="張飛",25,.sno = 1002 這樣賦值,例如
struct student st;
st = {100,"abc",22,95.7};    //錯誤
但是:同類型的結構體變數之間可以相互賦值,例如:
struct student st;
//st = {1001,"張飛",25,98.1};   //錯誤的
st = st1;   //正確的
另外,也可以分別給每一個成員賦值,例如:
st.sno = 1001;
strcpy(st.name,"趙雲");
st.age = 26;
st.score = 95.7;

2》列印:
不能整體列印,必須分別列印每一個成員,例如:
printf("st1:%d,%s,%d,%f\n",st1.sno,st1.name,st1.age,st1.score);
printf("st2:%d,%s,%d,%f\n",st2.sno,st2.name,st2.age,st2.score);
printf("st3:%d,%s,%d,%f\n",st3.sno,st3.name,st3.age,st3.score);
printf("st:%d,%s,%d,%f\n",st.sno,st.name,st.age,st.score);
3》傳參:
1)值傳遞

void fun1(struct student st){printf("st:%d,%s,%d,%f\n",st.sno,st.name,st.age,st.score);st.sno = 1001;strcpy(st.name,"趙雲");st.age = 26;st.score = 95.7;}
2)地址傳遞

void fun2(struct student * pst){printf("in_fun2:%d,%s,%d,%f\n",(*pst).sno,(*pst).name,(*pst).age,(*pst).score);(*pst).sno = 1001;strcpy((*pst).name,"趙雲");(*pst).age = 26;(*pst).score = 95.7;}
int main(void){struct student  st1 = {1001,"張飛",25,98.1};  //st2為結構體變數#if 0fun1(st1);   //值傳遞printf("st1:%d,%s,%d,%f\n",st1.sno,st1.name,st1.age,st1.score);#elsefun2(&st1);  //地址傳遞printf("st1:%d,%s,%d,%f\n",st1.sno,st1.name,st1.age,st1.score);#endifreturn 0;}
6、結構體數組
元素為結構體類型的數組稱為結構體數組,例如:
#include <stdio.h>#include <string.h>//結構體類型定義struct student{int sno;char name[20];int age;float score;};int main(void){struct student st[50] = {{1001,"張三",25,99},{1002,"李四",22,95},{1003,"王五",26,97}};int i;for(i = 0; i < 3; i++)printf("%d,%s,%d,%f\n",st[i].sno,st[i].name,st[i].age,st[i].score);return 0;}
7、結構體指標
指向結構體變數的指標稱為結構體指標,例如:

#include <stdio.h>//結構體類型定義struct student{int sno;char name[20];int age;float score;};int main(void){struct student st = {1001,"張三",25,99};struct student *pst;pst = &st;printf("%d,%s,%d,%f\n",st.sno,st.name,st.age,st.score);printf("%d,%s,%d,%f\n",(*pst).sno,(*pst).name,(*pst).age,(*pst).score);printf("%d,%s,%d,%f\n",pst->sno,pst->name,pst->age,pst->score);return 0;}
8、結構體成員類型:
1》基本類型:
struct A{
int a;
float b;
};
2》數組:
struct A{
int a[5];
float b;
};
3》結構體:
#include <stdio.h>struct A{int a;float b;};#if 0struct B{int x;struct A y;   //用已有的結構體類型定義成員變數};#elsestruct B{int x;//定義一個新的結構體類型同時定義該結構體變數struct {int a;float b;}y;};#endifint main(void){struct B st = {100,{123,34.56}};printf("%d,%d,%f\n",st.x,st.y.a,st.y.b);return 0;}
4》指標:

#include <stdio.h>struct A{int a;int *p;};int main(void){int x = 123;struct A st = {100,&x};printf("%d,%d\n",st.a,*st.p);return 0;}
5》結構體指標:
例1:

#include <stdio.h>struct A{int a;float b;};struct B{int x;struct A *pst;};int main(void){struct A sta = {123,3.5};struct B stb = {100,&sta};printf("%d\n",stb.x);printf("%d,%f\n",stb.pst->a,stb.pst->b);return 0;}
例2:

#include <stdio.h>typedef struct B{int x;struct B *pst;}ST;typedef struct node{int data;struct node *next;}list,*plist;int main(void){ST  st1 = {100,NULL};ST  st2 = {200,&st1};ST  st = {300,&st};list nd = {1000};plist pnd = &nd;printf("pnd->data = %d\n",pnd->data);printf("%d\n",st2.x);printf("%d\n",st2.pst->x);printf("%d,%d\n",st.x,st.pst->x);return 0;}
二、共用體
也叫聯合體,是一種複合資料型別,C語言中也沒有該類型的具體定義,但是給出了定義該類型的文法格式
也是由不同類型資料群組成,但是共用體中的多個資料共同使用同一塊記憶體空間。
1、共用體類型的定義
union <共用體標籤>{
成員類型  成員名;
成員類型  成員名;
....    ....
成員類型  成員名;
};
例如:定義一個共用體的類型
union student{
int sno;
char name[20];
int age;
float score;
};
2、共用體變數的定義
1》常規定義:
union student{
int sno;
char name[20];
int age;
float score;
};
union student  st1;  //st1為共用體變數
2》與類型同時定義
union student{
int sno;
char name[20];
int age;
float score;
}st2; /st2為共用體變數
3》直接定義
union {
int sno;
char name[20];
int age;
float score;
}st3; /st3為共用體變數


3、使用
1》賦值和列印與結構體類似,例如:

#include <stdio.h>#include <string.h>//共用體類型的定義union A{short a;char b[3];char c[5];};int main(void){union A u1;printf("sizeof(union A) = %d\n",sizeof(union A));printf("sizeof(u1) = %d\n",sizeof(u1));printf("sizeof(u1.a) = %d\n",sizeof(u1.a));printf("sizeof(u1.b) = %d\n",sizeof(u1.b));printf("sizeof(u1.f) = %d\n",sizeof(u1.c));#if 0/*************************************/u1.b = 12.34;strcpy(u1.c,"hello");u1.a = 123;printf("u1.a = %d\n",u1.a);printf("u1.b = %f\n",u1.b);printf("u1.c = %s\n",u1.c);/*************************************/strcpy(u1.c,"hello");u1.a = 123;u1.b = 12.34;printf("u1.a = %d\n",u1.a);printf("u1.b = %f\n",u1.b);printf("u1.c = %s\n",u1.c);/*************************************/#endif#if 0u1.a = 123;u1.b = 12.34;strcpy(u1.c,"hello");printf("u1.a = %d\n",u1.a);printf("u1.b = %f\n",u1.b);printf("u1.c = %s\n",u1.c);#endifreturn 0;}
總結:
1》共用體的成員共同使用同一塊記憶體空間
2》在程式中,某一時刻只有一個成員的值有效,即最後被賦值的成員有效
執行個體:
判斷機器的位元組序。

#include <stdio.h>#include <string.h>union A{unsigned int word;unsigned char byte;};int main(void){union A u1;u1.word = 0x12345678;if(u1.byte == 0x12)printf("大端序!\n");elseprintf("小端序!\n");return 0;}
三、枚舉類型
該類型的本質是整型,為了提高程式額可讀性,同時為了人為的程式中的一些資料規定一個取值的範圍,而設計出這樣的枚舉類型,例如
在程式中表示一周的每一天,或者一年中的每個月都可以定義成枚舉類型
1、枚舉類型的定義
enum <枚舉標籤>{
枚舉常量,
枚舉常量,
.....
枚舉常量
};
例如:
enum phone_color{
white, //枚舉常量
black, //枚舉常量
golden //枚舉常量
};
預設情況下,枚舉常量的值,從第一個開始依次是:0,1,2,3,....
enum phone_color   color;    //color為枚舉變數,一般在程式中取枚舉常量的值

#include <stdio.h>#include <string.h>enum phone_color{white,//枚舉常量black,//枚舉常量golden//枚舉常量};enum A{a1 = 100,a2,a3,a4 = 99,a5,a6};struct phone{float value;enum phone_color color;};int main(void){printf("white : %d\n",white);printf("black: %d\n",black);printf("golden : %d\n",golden);printf("a1 = %d\n",a1);printf("a2 = %d\n",a2);printf("a3 = %d\n",a3);printf("a4 = %d\n",a4);printf("a5 = %d\n",a5);printf("a6 = %d\n",a6);struct phone  apple = {5000,white};return 0;}
四、地址對齊
1、自然對齊
在資料分配空間時,如果該資料的起始地址能夠被它的長度整除,則就是自然對齊
2、資料的M值
如果該資料的長度小於機器字長,則M值為該資料的長度
如果該資料的長度大於等於機器字長,則M值為機器字長。
3、適當對齊
在資料分配空間時,如果該資料的起始地址能夠被它的M值整除,則就是適當對齊
4、不同類型資料的對齊
1》基本類型資料
按M值適當對齊
2》數組:
按元素的M值對齊
4》共用體:
按共用體變數的M值對齊,即:成員中M值最大的
5》結構體:
按結構體變數的M值對齊,即:成員中M值最大的

五、LinuxC語言中的一些特殊函數
1、遞迴函式
如果一個函數體內部,調用它自己,則該函數稱為遞迴函式,例如:

#include <stdio.h>#if 0void fun(int x,int y){printf("%d\n",x+y);}void test(void){int a = 3,b = 5;fun(a,b);}#elsevoid test(int i){printf("i = %d\n",i++);if(i < 5)test(i);}#endifint fun(int n){if(n == 1)return 1;else if(n > 1)return n*fun(n-1);elsereturn 1;}int main(void){int n;scanf("%d",&n);printf("%d\n",fun(n));return 0;}
2、變參函數
調用時,可以傳不同類型的參數或者傳不同個數的參數,這樣的函數稱為變參函數。
 int printf(const char *format, ...);
#include <stdio.h>#include <stdarg.h>void myprint(int n,...){va_list p;int i,t;va_start(p,n);  //對p初始化for(i = 0; i < n; i++){t = va_arg(p,int);printf("%d\t",t);}printf("\n");va_end(p);}int main(void){myprint(5,1,2,3,4,5);myprint(5,111,222,333,444,555);myprint(10,1,2,3,4,5,6,7,8,9,10);return 0;}
3、回呼函數
指的是函數調用的一種方式,簡單來說:間接調用的函數稱為回呼函數,例如:


4、內嵌函式









聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.