1. 結(jié)構體介紹
C語言里的結(jié)構體是可以包含不同數(shù)據(jù)類型和相同數(shù)據(jù)類型的一個有序集合,屬于構造類型,可以自己任意組合,并且結(jié)構體里也可以使用結(jié)構體類型作為成員。
結(jié)構體在項目開發(fā)中使用非常多,無處不在,有了結(jié)構體類型就可以設計很多框架,模型,方便數(shù)據(jù)傳輸,存儲等等。
結(jié)構體定義語法
struct 結(jié)構體名稱
{
    數(shù)據(jù)類型1 成員名1;
    數(shù)據(jù)類型2 成員名2;
    數(shù)據(jù)類型3 成員名3;
    .....
};
結(jié)構體的名稱命名規(guī)則: 和普通變量命名規(guī)則一樣—遵循C語言變量命名標準。
                       ‘A’~‘Z’ ‘a(chǎn)’~ ’z’  ‘0’~’9’  _
示例代碼:
struct app
{
    int age; //年齡
    char name[100]; //姓名
    int number; //學號
};
上面這一塊代碼表示定義(聲明)一個新的結(jié)構體類型。  數(shù)據(jù)類型名稱:struct app
2. 如何使用結(jié)構體定義變量?
結(jié)構體定義變量有3種形式:
#include 
//第一種形式:在定義結(jié)構體類型的時候同時定義變量
struct app1
{
    int age; //年齡
    char name[100]; //姓名
    int number; //學號
}a1,a2,a3;   //a1 a2 a3就是定義的結(jié)構體變量
//第二種形式
struct app2
{
    int age; //年齡
    char name[100]; //姓名
    int number; //學號
};
//第三種形式: 匿名方式定義結(jié)構體
struct
{
    int age; //年齡
    char name[100]; //姓名
    int number; //學號
}c1,c2,c3;  //c1 c2 c3就是定義的結(jié)構體變量
int main()
{
    //使用結(jié)構體類型定義變量
    struct app2 b1;
    struct app2 b2;
    struct app2 b3;
    return 0;
}
3. 結(jié)構體的賦值
結(jié)構體變量的賦值語法:
 結(jié)構體變量名.成員名=xxx;
結(jié)構體初始化賦值說明:
結(jié)構體只能在(定義結(jié)構體變量的時候)初始化的時候支持整體賦值,之后就只能按照成員單個賦值。
注意:結(jié)構體變量之間支持直接賦值。
#include 
#include 
//第一種形式:在定義結(jié)構體類型的時候同時定義變量
struct app1
{
    int age; //年齡
    char name[100]; //姓名
    int number; //學號
}a1={23,"小白",5678},a2,a3={12,"小明",1234};   //a1 a2 a3就是定義的結(jié)構體變量
//第二種形式
struct app2
{
    int age; //年齡
    char name[100]; //姓名
    int number; //學號
};
int main()
{
    //使用結(jié)構體類型定義變量
    struct app2 b1={15,"小李",6878};
    struct app2 b2;
    struct app2 b3;
    //單個修改結(jié)構體成員變量的值
    b1.age=18;
    //b1.name="555";
    strcpy(b1.name,"小麗");
   
    printf("b1:%d\n",b1.age);
    printf("b1:%s\n",b1.name);
    printf("a1:%d\n",a1.age);
    printf("a1:%s\n",a1.name);
    //結(jié)構體變量之間支持直接賦值 (要保證變量的類型要一致)。
   //int a=100;
   //int b;
   //b=a;
   b2=b1;  //將b1結(jié)構體變量賦值給b2結(jié)構體變量
   printf("b2:%d\n",b2.age);
   printf("b2:%s\n",b2.name);
    return 0;
}
4. 結(jié)構體指針定義與使用
示例代碼:
#include 
#include 
#include 
struct app
{
    int age; //年齡
    char name[100]; //姓名
    int number; //學號
}; 
int main()
{
    struct app a1;   //定義一個結(jié)構體變量
    struct app *p1;  //定義一個結(jié)構體指針
    struct app *p2;  //定義一個結(jié)構體指針
    p1=&a1;  //地址賦值  p1指向a1的空間
    //申請堆空間
    p2=malloc(sizeof(struct app));
    //通過指針訪問成員
    p1->age=20;
    strcpy(p1->name,"小紅");
    p1->number=1234;
    //輸出數(shù)據(jù)
    printf("姓名:%s\n",p1->name);
    printf("學號:%d\n",p1->number);
    printf("年齡:%d\n",p1->age);
     //通過指針訪問成員
    p2->age=13;
    strcpy(p2->name,"小李");
    p2->number=5678;
    //輸出數(shù)據(jù)
    printf("姓名:%s\n",p2->name);
    printf("學號:%d\n",p2->number);
    printf("年齡:%d\n",p2->age);
    //釋放空間
    free(p2);
    return 0;
}
5. 結(jié)構體數(shù)組定義與使用
示例代碼:
#include 
#include 
#include 
struct app
{
    int age; //年齡
    char name[100]; //姓名
    int number; //學號
}; 
int main()
{
    
    //定義一個結(jié)構體數(shù)組
    struct app buff[10];  //一次定義了10個結(jié)構體變量
    struct app *p=buff;  //定義一個結(jié)構體指針
    //訪問成員
    buff[0].age=10;
    strcpy(buff[0].name,"小米");
    buff[0].number=1234;
    //打印數(shù)據(jù)
    printf("姓名:%s\n",buff[0].name);
    printf("學號:%d\n",buff[0].number);
    printf("年齡:%d\n",buff[0].age);
    printf("姓名:%s\n",p[0].name);
    printf("學號:%d\n",p[0].number);
    printf("年齡:%d\n",p[0].age);
    return 0;
}
6. 結(jié)構體當做函數(shù)的形參和返回值
示例代碼:
#include 
#include 
#include 
struct app
{
    int age; //年齡
    char name[100]; //姓名
    int number; //學號
}; 
struct app *func_stu(struct app *p);
int main()
{
    
    //定義一個結(jié)構體數(shù)組
    struct app buff[10];  //一次定義了10個結(jié)構體變量
   
    //調(diào)用函數(shù)
    func_stu(&buff[0]);
    //打印數(shù)據(jù)
    printf("姓名:%s\n",buff[0].name);
    printf("學號:%d\n",buff[0].number);
    printf("年齡:%d\n",buff[0].age);
    return 0;
}
//定義函數(shù)
struct app *func_stu(struct app *p)
{
   //訪問成員
    p->age=10;
    strcpy(p->name,"小米");
    p->number=1234;
    return p;
}
7. typedef關鍵字在結(jié)構體里使用方法
#include 
#include 
#include 
typedef struct app
{
    int age; //年齡
    char name[100]; //姓名
    int number; //學號
}STU;  //STU叫結(jié)構體類型,相當于struct app的別名。  struct app == STU
STU *func_stu(STU *p);
int main()
{
    //定義一個結(jié)構體數(shù)組
    STU buff[10];  //一次定義了10個結(jié)構體變量
   
    //調(diào)用函數(shù)
    func_stu(&buff[0]);
    //打印數(shù)據(jù)
    printf("姓名:%s\n",buff[0].name);
    printf("學號:%d\n",buff[0].number);
    printf("年齡:%d\n",buff[0].age);
    return 0;
}
//定義函數(shù)
STU *func_stu(STU *p)
{
   //訪問成員
    p->age=10;
    strcpy(p->name,"小米");
    p->number=1234;
    return p;
}
8. 結(jié)構體位域
位域用的不多,但是也有地方使用,主要是節(jié)省空間。
#include 
struct app
{
    unsigned int a:12;  //定義位域,指定位寬   12的單位是位
    unsigned int b:16;
    unsigned char c:1; //定義空間存儲1位的數(shù)據(jù)。  1和0
    unsigned int :5;   //位域的名稱可以省略掉,為了空間內(nèi)存對齊而存在的
};
/*
1. 位域的大小不能超出本來數(shù)據(jù)類型大小。
2. 位域的名稱可以省略掉,為了空間內(nèi)存對齊而存在的
3. 位域的成員無法取地址操作
*/
int main()
{
    struct app data;
    //data.c=2;  錯誤 超出范圍   只能存放0~1
    //data.b=65535;   錯誤 超出范圍   只能存放0~65535
    // data.a=4096; 錯誤 超出范圍   只能存放0~65535
    //printf("%d\n",data.c);
   // printf("%d\n",data.b);
    //printf("%d\n",data.a);
    //printf("%d\n",&data.a);   //錯誤 位域的成員無法取地址操作
    data.c=1;
    data.b=555; //只能存放0~65535
    data.a=888; //只能存放0~65535
    printf("%d\n",data.c);
    printf("%d\n",data.b);
    printf("%d\n",data.a);
    return 0;
}
9. 結(jié)構體的內(nèi)存對齊
9.1 示例1: 計算結(jié)構體內(nèi)存對齊
#include 
struct app
{
   int a1;
   char a2;
   char a3;
   char a4;
   char a5;
   char a6;
   char a7;
};
/*
目前32位系統(tǒng)里,使用的是gcc編譯器。
開空間的對齊原理:以結(jié)構體里出現(xiàn)的最大數(shù)據(jù)類型的倍數(shù)開空間,最大是4個字節(jié)。
*/
int main()
{
    struct app data;
    printf("空間大小:%d 字節(jié)\n",sizeof(struct app)); //8
    return 0;
}
//func("1",1123,45,"45",123.45,'A');
void func(char *p,...)
{
}
9.2 示例2: 計算結(jié)構體內(nèi)存對齊
#include 
#if 0
struct app
{
   char a1;  //1
   short a2; //2
};
最終占用空間大小4個字節(jié)
#endif
#if 0
struct app
{
   int a1[10];   //4*10=40
   char a2[10];  //12
   int a3;      //4
   float a4;   //4
   char a5;   //4
};
//最終占用空間大小64個字節(jié)
#endif
#if 1
struct app
{
   int a1;
   double a2;
};
//最終占用空間大小64個字節(jié)
#endif
/*
目前32位系統(tǒng)里,使用的是gcc編譯器。
開空間的對齊原理:以結(jié)構體里出現(xiàn)的最大數(shù)據(jù)類型的倍數(shù)開空間,最大是4個字節(jié)。
*/
int main()
{
    struct app data;
    printf("空間大小:%d 字節(jié)\n",sizeof(struct app)); //8
    return 0;
}
//func("1",1123,45,"45",123.45,'A');
void func(char *p,...)
{
}
9.3 輸出結(jié)構體變量成員的地址,查看空間對齊情況
#include 
struct app
{
   int a1[10];   //4*10=40
   char a2[10];  //12
   int a3;      //4
   float a4;   //4
   char a5;   //4
};
//最終占用空間大小64個字節(jié)
int main()
{
    struct app data;
    //輸出地址   查看空間對齊原理
    printf("%#x\n",data.a1);
    printf("%#x\n",data.a2);
    printf("%#x\n",&data.a3);
    printf("%#x\n",&data.a4);
    printf("%#x\n",&data.a5);
    return 0;
}
9.4 對齊結(jié)構體進行強制對齊
#include 
#pragma pack(1)  //1 2 4 8
struct app
{
   int a1[10];   //4*10=40
   char a2[10];  //1*10=10
   int a3;      //4
   float a4;   //4
   char a5;   //1
};
int main()
{
    struct app data;
    //輸出地址   查看空間對齊原理
    printf("%#x\n",data.a1);
    printf("%#x\n",data.a2);
    printf("%#x\n",&data.a3);
    printf("%#x\n",&data.a4);
    printf("%#x\n",&data.a5);
    printf("%d\n",sizeof(struct app));
    return 0;
}
                                        - 
                                C語言
                                +關注
關注
183文章
7636瀏覽量
144296 - 
                                結(jié)構體
                                +關注
關注
1文章
131瀏覽量
11278 
發(fā)布評論請先 登錄
C語言中數(shù)組和結(jié)構體的內(nèi)存表示和布局
用C語言的結(jié)構體實現(xiàn)字節(jié)、位操作
430編程C語言常識(IAR)之結(jié)構體與聯(lián)合體
【武漢華嵌】結(jié)構體的sizeof問題
C結(jié)構體之位域位段
漫談C語言結(jié)構體
在c語言中的位域(位段)是如何去定義的?有哪些限制呢
C語言結(jié)構體之位域位段
C語言中的位域是什么?
C語言之位域使用
    
          
        
        
C語言-結(jié)構體與位域
                
 
           
            
            
                
            
評論