0
  • 聊天消息
  • 系統(tǒng)消息
  • 評(píng)論與回復(fù)
登錄后你可以
  • 下載海量資料
  • 學(xué)習(xí)在線課程
  • 觀看技術(shù)視頻
  • 寫文章/發(fā)帖/加入社區(qū)
會(huì)員中心
創(chuàng)作中心

完善資料讓更多小伙伴認(rèn)識(shí)你,還能領(lǐng)取20積分哦,立即完善>

3天內(nèi)不再提示

C語言-結(jié)構(gòu)體與位域

DS小龍哥-嵌入式技術(shù) ? 來源:DS小龍哥-嵌入式技術(shù) ? 作者:DS小龍哥-嵌入式技 ? 2022-08-14 10:06 ? 次閱讀

1. 結(jié)構(gòu)體介紹

C語言里的結(jié)構(gòu)體是可以包含不同數(shù)據(jù)類型和相同數(shù)據(jù)類型的一個(gè)有序集合,屬于構(gòu)造類型,可以自己任意組合,并且結(jié)構(gòu)體里也可以使用結(jié)構(gòu)體類型作為成員。

結(jié)構(gòu)體在項(xiàng)目開發(fā)中使用非常多,無處不在,有了結(jié)構(gòu)體類型就可以設(shè)計(jì)很多框架,模型,方便數(shù)據(jù)傳輸,存儲(chǔ)等等。

結(jié)構(gòu)體定義語法

struct 結(jié)構(gòu)體名稱
{
    數(shù)據(jù)類型1 成員名1;
    數(shù)據(jù)類型2 成員名2;
    數(shù)據(jù)類型3 成員名3;
    .....
};

結(jié)構(gòu)體的名稱命名規(guī)則: 和普通變量命名規(guī)則一樣—遵循C語言變量命名標(biāo)準(zhǔn)。
                       ‘A’~‘Z’ ‘a(chǎn)’~ ’z’  ‘0’~’9’  _

示例代碼:

struct app
{
    int age; //年齡
    char name[100]; //姓名
    int number; //學(xué)號(hào)
};

上面這一塊代碼表示定義(聲明)一個(gè)新的結(jié)構(gòu)體類型。  數(shù)據(jù)類型名稱:struct app

2. 如何使用結(jié)構(gòu)體定義變量?

結(jié)構(gòu)體定義變量有3種形式:

#include 

//第一種形式:在定義結(jié)構(gòu)體類型的時(shí)候同時(shí)定義變量
struct app1
{
    int age; //年齡
    char name[100]; //姓名
    int number; //學(xué)號(hào)
}a1,a2,a3;   //a1 a2 a3就是定義的結(jié)構(gòu)體變量

//第二種形式
struct app2
{
    int age; //年齡
    char name[100]; //姓名
    int number; //學(xué)號(hào)
};

//第三種形式: 匿名方式定義結(jié)構(gòu)體
struct
{
    int age; //年齡
    char name[100]; //姓名
    int number; //學(xué)號(hào)
}c1,c2,c3;  //c1 c2 c3就是定義的結(jié)構(gòu)體變量

int main()
{
    //使用結(jié)構(gòu)體類型定義變量
    struct app2 b1;
    struct app2 b2;
    struct app2 b3;

    return 0;
}

3. 結(jié)構(gòu)體的賦值

結(jié)構(gòu)體變量的賦值語法:

 結(jié)構(gòu)體變量名.成員名=xxx;

結(jié)構(gòu)體初始化賦值說明:

結(jié)構(gòu)體只能在(定義結(jié)構(gòu)體變量的時(shí)候)初始化的時(shí)候支持整體賦值,之后就只能按照成員單個(gè)賦值。

注意:結(jié)構(gòu)體變量之間支持直接賦值。

#include 
#include 

//第一種形式:在定義結(jié)構(gòu)體類型的時(shí)候同時(shí)定義變量
struct app1
{
    int age; //年齡
    char name[100]; //姓名
    int number; //學(xué)號(hào)
}a1={23,"小白",5678},a2,a3={12,"小明",1234};   //a1 a2 a3就是定義的結(jié)構(gòu)體變量

//第二種形式
struct app2
{
    int age; //年齡
    char name[100]; //姓名
    int number; //學(xué)號(hào)
};

int main()
{
    //使用結(jié)構(gòu)體類型定義變量
    struct app2 b1={15,"小李",6878};
    struct app2 b2;
    struct app2 b3;

    //單個(gè)修改結(jié)構(gòu)體成員變量的值
    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é)構(gòu)體變量之間支持直接賦值 (要保證變量的類型要一致)。
   //int a=100;
   //int b;
   //b=a;
   b2=b1;  //將b1結(jié)構(gòu)體變量賦值給b2結(jié)構(gòu)體變量
   printf("b2:%d\n",b2.age);
   printf("b2:%s\n",b2.name);
    return 0;
}

4. 結(jié)構(gòu)體指針定義與使用

示例代碼:

#include 
#include 
#include 

struct app
{
    int age; //年齡
    char name[100]; //姓名
    int number; //學(xué)號(hào)
}; 

int main()
{
    struct app a1;   //定義一個(gè)結(jié)構(gòu)體變量
    struct app *p1;  //定義一個(gè)結(jié)構(gòu)體指針
    struct app *p2;  //定義一個(gè)結(jié)構(gòu)體指針
    p1=&a1;  //地址賦值  p1指向a1的空間

    //申請(qǐng)堆空間
    p2=malloc(sizeof(struct app));

    //通過指針訪問成員
    p1->age=20;
    strcpy(p1->name,"小紅");
    p1->number=1234;
    //輸出數(shù)據(jù)
    printf("姓名:%s\n",p1->name);
    printf("學(xué)號(hào):%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("學(xué)號(hào):%d\n",p2->number);
    printf("年齡:%d\n",p2->age);

    //釋放空間
    free(p2);
    return 0;
}

5. 結(jié)構(gòu)體數(shù)組定義與使用

示例代碼:

#include 
#include 
#include 

struct app
{
    int age; //年齡
    char name[100]; //姓名
    int number; //學(xué)號(hào)
}; 

int main()
{
    
    //定義一個(gè)結(jié)構(gòu)體數(shù)組
    struct app buff[10];  //一次定義了10個(gè)結(jié)構(gòu)體變量
    struct app *p=buff;  //定義一個(gè)結(jié)構(gòu)體指針

    //訪問成員
    buff[0].age=10;
    strcpy(buff[0].name,"小米");
    buff[0].number=1234;

    //打印數(shù)據(jù)
    printf("姓名:%s\n",buff[0].name);
    printf("學(xué)號(hào):%d\n",buff[0].number);
    printf("年齡:%d\n",buff[0].age);

    printf("姓名:%s\n",p[0].name);
    printf("學(xué)號(hào):%d\n",p[0].number);
    printf("年齡:%d\n",p[0].age);
    return 0;
}

6. 結(jié)構(gòu)體當(dāng)做函數(shù)的形參和返回值

示例代碼:

#include 
#include 
#include 

struct app
{
    int age; //年齡
    char name[100]; //姓名
    int number; //學(xué)號(hào)
}; 

struct app *func_stu(struct app *p);

int main()
{
    
    //定義一個(gè)結(jié)構(gòu)體數(shù)組
    struct app buff[10];  //一次定義了10個(gè)結(jié)構(gòu)體變量
   
    //調(diào)用函數(shù)
    func_stu(&buff[0]);

    //打印數(shù)據(jù)
    printf("姓名:%s\n",buff[0].name);
    printf("學(xué)號(hào):%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關(guān)鍵字在結(jié)構(gòu)體里使用方法

#include 
#include 
#include 

typedef struct app
{
    int age; //年齡
    char name[100]; //姓名
    int number; //學(xué)號(hào)
}STU;  //STU叫結(jié)構(gòu)體類型,相當(dāng)于struct app的別名。  struct app == STU

STU *func_stu(STU *p);

int main()
{
    //定義一個(gè)結(jié)構(gòu)體數(shù)組
    STU buff[10];  //一次定義了10個(gè)結(jié)構(gòu)體變量
   
    //調(diào)用函數(shù)
    func_stu(&buff[0]);

    //打印數(shù)據(jù)
    printf("姓名:%s\n",buff[0].name);
    printf("學(xué)號(hào):%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é)構(gòu)體位域

位域用的不多,但是也有地方使用,主要是節(jié)省空間。

#include 
struct app
{
    unsigned int a:12;  //定義位域,指定位寬   12的單位是位
    unsigned int b:16;
    unsigned char c:1; //定義空間存儲(chǔ)1位的數(shù)據(jù)。  1和0
    unsigned int :5;   //位域的名稱可以省略掉,為了空間內(nèi)存對(duì)齊而存在的
};
/*
1. 位域的大小不能超出本來數(shù)據(jù)類型大小。
2. 位域的名稱可以省略掉,為了空間內(nèi)存對(duì)齊而存在的
3. 位域的成員無法取地址操作
*/

int main()
{
    struct app data;
    //data.c=2;  錯(cuò)誤 超出范圍   只能存放0~1
    //data.b=65535;   錯(cuò)誤 超出范圍   只能存放0~65535
    // data.a=4096; 錯(cuò)誤 超出范圍   只能存放0~65535
    //printf("%d\n",data.c);
   // printf("%d\n",data.b);
    //printf("%d\n",data.a);

    //printf("%d\n",&data.a);   //錯(cuò)誤 位域的成員無法取地址操作

    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é)構(gòu)體的內(nèi)存對(duì)齊

9.1 示例1: 計(jì)算結(jié)構(gòu)體內(nèi)存對(duì)齊

#include 
struct app
{
   int a1;
   char a2;
   char a3;
   char a4;
   char a5;
   char a6;
   char a7;
};
/*
目前32位系統(tǒng)里,使用的是gcc編譯器。
開空間的對(duì)齊原理:以結(jié)構(gòu)體里出現(xiàn)的最大數(shù)據(jù)類型的倍數(shù)開空間,最大是4個(gè)字節(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: 計(jì)算結(jié)構(gòu)體內(nèi)存對(duì)齊

#include 
#if 0
struct app
{
   char a1;  //1
   short a2; //2
};
最終占用空間大小4個(gè)字節(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個(gè)字節(jié)
#endif

#if 1
struct app
{
   int a1;
   double a2;
};
//最終占用空間大小64個(gè)字節(jié)
#endif

/*
目前32位系統(tǒng)里,使用的是gcc編譯器。
開空間的對(duì)齊原理:以結(jié)構(gòu)體里出現(xiàn)的最大數(shù)據(jù)類型的倍數(shù)開空間,最大是4個(gè)字節(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é)構(gòu)體變量成員的地址,查看空間對(duì)齊情況

#include 

struct app
{
   int a1[10];   //4*10=40
   char a2[10];  //12
   int a3;      //4
   float a4;   //4
   char a5;   //4
};
//最終占用空間大小64個(gè)字節(jié)

int main()
{
    struct app data;

    //輸出地址   查看空間對(duì)齊原理
    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 對(duì)齊結(jié)構(gòu)體進(jìn)行強(qiáng)制對(duì)齊

#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;

    //輸出地址   查看空間對(duì)齊原理
    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;
}
聲明:本文內(nèi)容及配圖由入駐作者撰寫或者入駐合作網(wǎng)站授權(quán)轉(zhuǎn)載。文章觀點(diǎn)僅代表作者本人,不代表電子發(fā)燒友網(wǎng)立場。文章及其配圖僅供工程師學(xué)習(xí)之用,如有內(nèi)容侵權(quán)或者其他違規(guī)問題,請(qǐng)聯(lián)系本站處理。 舉報(bào)投訴
  • C語言
    +關(guān)注

    關(guān)注

    180

    文章

    7575

    瀏覽量

    134239
  • 結(jié)構(gòu)體
    +關(guān)注

    關(guān)注

    1

    文章

    127

    瀏覽量

    10804
收藏 人收藏

    評(píng)論

    相關(guān)推薦

    C語言中數(shù)組和結(jié)構(gòu)的內(nèi)存表示和布局

    C語言中,數(shù)組和結(jié)構(gòu)都可以代表一塊內(nèi)存,但為什么結(jié)構(gòu)可以直接賦值,而數(shù)組不可以?這個(gè)問題涉及
    發(fā)表于 08-28 10:54 ?1173次閱讀

    C語言結(jié)構(gòu)講解

    C語言中有一塊極容易被忽略,但是對(duì)于嵌入式編程來說用處特別大的內(nèi)容——結(jié)構(gòu)
    發(fā)表于 10-01 13:27 ?291次閱讀
    <b class='flag-5'>C</b><b class='flag-5'>語言</b><b class='flag-5'>結(jié)構(gòu)</b><b class='flag-5'>體</b>講解

    C語言結(jié)構(gòu)實(shí)現(xiàn)字節(jié)、操作

    C語言結(jié)構(gòu)實(shí)現(xiàn)字節(jié)、操作結(jié)構(gòu)化程序設(shè)計(jì)是編寫清晰、正確和易于修改的程序。而對(duì)于大多數(shù)編程
    發(fā)表于 09-21 09:25

    430編程C語言常識(shí)(IAR)之結(jié)構(gòu)與聯(lián)合體

    z4 : 4;  };  z = 0xFFFF;  a = z1;  b = z2;  c = z3;  復(fù)制代碼結(jié)果:a = 1, b = 3, c = 7;  (4)結(jié)構(gòu)中的
    發(fā)表于 11-22 15:43

    C結(jié)構(gòu)

    有些信息在存儲(chǔ)時(shí),并不需要占用一個(gè)完整的字節(jié), 而只需占幾個(gè)或一個(gè)二進(jìn)制。例如在存放一個(gè)開關(guān)量時(shí),只有0和1 兩種狀態(tài), 用一二進(jìn)位即可。為了節(jié)省存儲(chǔ)空間,并使處理簡便,C語言又提
    發(fā)表于 12-10 20:35

    漫談C語言結(jié)構(gòu)

      相信大家對(duì)于結(jié)構(gòu)都不陌生。在此,分享出本人對(duì)c語言結(jié)構(gòu)的學(xué)習(xí)心得。如果你發(fā)現(xiàn)這個(gè)總結(jié)中有
    發(fā)表于 11-15 15:59

    為什么結(jié)構(gòu)與聯(lián)合體一起使用?

    /*本例程是C語言操作示例這里為什么結(jié)構(gòu)
    發(fā)表于 07-14 06:23

    是怎樣去定義的

    一、描述存放一個(gè)開關(guān)量或者其他開關(guān)狀態(tài)時(shí),用一二進(jìn)位即可。為了減少嵌入式內(nèi)存資源的開銷,可以使用進(jìn)行定義,
    發(fā)表于 12-15 07:47

    怎樣去使用C語言結(jié)構(gòu)和共用

    C語言結(jié)構(gòu)和共用分別有何特點(diǎn)呢?怎樣去使用C語言
    發(fā)表于 01-17 07:51

    c語言中的段)是如何去定義的?有哪些限制呢

    c語言中提供一個(gè)一種叫 “” 或者 “段” 的數(shù)據(jù)結(jié)構(gòu)。它的存在是為了更加的節(jié)省空間。因
    發(fā)表于 07-01 15:52

    C語言結(jié)構(gòu)

    所謂""是把一個(gè)字節(jié)中的二進(jìn)位劃分為幾個(gè)不同的區(qū)域,并說明每個(gè)區(qū)域的位數(shù)。每個(gè)有一個(gè)域名,允許在程序中按域名進(jìn)行操作。這樣就可以把幾個(gè)不同的對(duì)象用一個(gè)字節(jié)的二進(jìn)制
    的頭像 發(fā)表于 11-08 08:38 ?7717次閱讀

    C語言中的是什么?

    是什么? 有些數(shù)據(jù)在存儲(chǔ)時(shí)并不需要占用一個(gè)完整的字節(jié),只需要占用一個(gè)或幾個(gè)二進(jìn)制即可。例如開關(guān)只有通電和斷電兩種狀態(tài),用 0 和 1 表示足以,也就是用一個(gè)二進(jìn)位。正是基于這種考慮,C
    的頭像 發(fā)表于 01-13 16:23 ?2872次閱讀

    C語言使用

    在單片機(jī)的編程中,會(huì)使用到一些IC里面的寄存器,而有些寄存器并不是每一都是有效的,例如:這里的1-3則是保留的,不可以被操作的。所以在對(duì)一些寄存器進(jìn)行操作時(shí),可以利用C語言
    發(fā)表于 01-12 20:47 ?6次下載
    <b class='flag-5'>C</b><b class='flag-5'>語言</b>之<b class='flag-5'>位</b><b class='flag-5'>域</b>使用

    C語言入門之結(jié)構(gòu)指針

    C語言中,指向結(jié)構(gòu)對(duì)象的指針變量既可以指向結(jié)構(gòu)變量,也可指向
    的頭像 發(fā)表于 03-24 14:59 ?923次閱讀

    C語言結(jié)構(gòu)完全筆記

    我們剛剛申請(qǐng)了一個(gè)名叫Info的結(jié)構(gòu)類型,那么理論上我們可以像聲明其他變量的操作一樣,去聲明我們的結(jié)構(gòu)體操作,但是C語言中規(guī)定,聲明
    的頭像 發(fā)表于 08-01 16:52 ?500次閱讀
    <b class='flag-5'>C</b><b class='flag-5'>語言</b><b class='flag-5'>結(jié)構(gòu)</b><b class='flag-5'>體</b>完全筆記