日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問(wèn) 生活随笔!

生活随笔

當(dāng)前位置: 首頁(yè) > 编程资源 > 综合教程 >内容正文

综合教程

结构体的概念

發(fā)布時(shí)間:2024/6/21 综合教程 34 生活家
生活随笔 收集整理的這篇文章主要介紹了 结构体的概念 小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

結(jié)構(gòu)體的概念

?C語(yǔ)言中有很多的基礎(chǔ)數(shù)據(jù)類(lèi)型,除了這些我們可以通過(guò)一個(gè)結(jié)構(gòu)體來(lái)把一部分基礎(chǔ)數(shù)據(jù)類(lèi)型整合為一個(gè)新的自定義類(lèi)型。

struct 結(jié)構(gòu)體的標(biāo)簽 {

      成員1 ; 
      成員2 ;
       ..... 
}; // 最后用一個(gè)分號(hào)來(lái)表示結(jié)束

?結(jié)構(gòu)體的標(biāo)簽 : 用來(lái)區(qū)分各個(gè)不同類(lèi)型的結(jié)構(gòu)體 (也可以省略)。
?成 員: 指的是該結(jié)構(gòu)體內(nèi)部的數(shù)據(jù),可以是任何數(shù)據(jù)類(lèi)型。也可是結(jié)構(gòu)體

結(jié)構(gòu)體聲明,定義

structnode { 

      inta; 
      charc; 
      doubled; 
}; 

intmain(intargc,charconst*argv[]) 
{ 
      //定義結(jié)構(gòu)體-->分配內(nèi)存空間 
      structnodea; 
} 

注意:
1.只有結(jié)構(gòu)體被定義時(shí)才會(huì)被分配內(nèi)存空間,結(jié)構(gòu)體聲明并不會(huì)分配內(nèi)存空間;
2.定義結(jié)構(gòu)體的步驟:
?a.分配一片內(nèi)存名字叫 a
?b.該內(nèi)存中需要存放一個(gè)結(jié)構(gòu)體
?c.分被存放的是 int a , char c ,double d

結(jié)構(gòu)體初始化

?結(jié)構(gòu)體與普通的變量都是一樣的,都設(shè)計(jì)涉及,初始化,賦值,取值,傳值等等操作。由于結(jié)構(gòu)體中的成員類(lèi)型各有不同因此有兩種初始化得到方法:
?1.普通初始化
??寫(xiě)起來(lái)方便,但是改起來(lái)一點(diǎn)都不方便。
?2.指定成員初始化
??寫(xiě)起來(lái)雖然累一點(diǎn)點(diǎn), 但是如果結(jié)構(gòu)體在后期有更新迭代,不會(huì)有初始化的效果。

//1.普通初始換 
structnodec={100,'M',3.1456676}; 
//2.指定成員初始化 
structnoded={ 
 
      .a=998, // . 稱(chēng)為成員引用符 
 .c='K', 
.d=2345.21345 
};

注意:
1.指定成員初始化:
?a.成員的次序或數(shù)量的變化不會(huì)導(dǎo)致初始化有邏輯問(wèn)題;
?b.可以初始化一部分成員;
?c.如果結(jié)構(gòu)體新增成員,該初始化語(yǔ)句依然可用。

結(jié)構(gòu)體成員引用

?由于結(jié)構(gòu)體內(nèi)部包含的成員不止一個(gè),所以說(shuō)需要使用 . 結(jié)構(gòu)體成員的引用符來(lái)訪問(wèn)其中指定的成員。

//結(jié)構(gòu)體變量.結(jié)構(gòu)體成員
printf("a:%d	c:%c	d:%lf
", d.a,d.c,d.d); 
d.a=123; d.c='M'; d.d=3.14; 
printf("a:%d	c:%c	d:%lf
", d.a,d.c,d.d); 

結(jié)構(gòu)體數(shù)組

結(jié)構(gòu)體數(shù)組與其他的普通變量的數(shù)組并沒(méi)有差別,只不過(guò)他的數(shù)組內(nèi)容為一個(gè)一個(gè)的結(jié)構(gòu)體。

structnodearr[10]; 
arr[0].a=200; 
arr[0].c='N'; 
arr[0].d=889.43; 

結(jié)構(gòu)體指針
?結(jié)構(gòu)體指針與其他指針沒(méi)有差別,只不過(guò)其指向的是一個(gè)結(jié)構(gòu)體。

structnode*p; 
p=&d; 
printf("p->a:%d	p->c:%c	p->d:%lf
", p->a,p->c,p->d); 

注意:
1.普通的結(jié)構(gòu)體成員引用使用 .;
2.指針的結(jié)構(gòu)體成員應(yīng)用使用 ->。

結(jié)構(gòu)體聲明的變異

structnode { 

      inta; 
      charc; 
      doubled; 
}; 
    //變形 1 
structnode { 

      inta; 
      charc; 
      doubled; 
}Even, GEC; // 在聲明結(jié)構(gòu)體的時(shí)候順便定義兩個(gè)結(jié)構(gòu)體變量
 
Even.a=100; Even.c='C'; Even.d=12312.234; 
printf("%d	%c	%lf
",Even.a,Even.c,Even.d); 
//變形 2
struct{// 結(jié)構(gòu)體的標(biāo)簽可以省略 ,但是省略的話以后沒(méi)法定義更多的此類(lèi)型結(jié)構(gòu)體 

      inta; 
      charc; 
      doubled; 
}Jacy; // 在聲明結(jié)構(gòu)體的時(shí)候順便定義一個(gè)結(jié)構(gòu)體變量 

    Jacy.a=200; 
    Jacy.c='A'; 
    Jacy.d=123.2; 
    printf("%d	%c	%lf
",Jacy.a,Jacy.c,Jacy.d); 



    //示例
structCuiHua { 

      inta; 
      charc; 
      doubled; 
      struct{ 

            char*p; 
            chararr[32]; 
      }Jacy;//在聲明結(jié)構(gòu)體的時(shí)候順便定義個(gè)結(jié)構(gòu)體變量 
}Even,GEC;//在聲明結(jié)構(gòu)體的時(shí)候順便定義兩個(gè)結(jié)構(gòu)體變量 

structCuiHuahua={ 

      .a=1024, 
      .c='B', 
      .d=123.123, 
      .Jacy.p="Hello",//p指向的是數(shù)據(jù)段中的Hello的地址 
      .Jacy.arr="GZ2069"http://數(shù)組arr屬于棧空間,它內(nèi)部存放了"GZ2069" 
};
 
printf("a:%d	c:%c	d:%lf	p:%s	arr:%s
", 
        hua.a,hua.c,hua.d,hua.Jacy.p, hua.Jacy.arr); 

hua.Jacy.p=malloc(32);//申請(qǐng)一篇堆空間大小為32字節(jié)讓P指向hello 
   
strncpy(hua.Jacy.p,"hello",32);
hua.Jacy.arr[0]='g'; hua.Jacy.arr[1]='z'; 
printf("a:%d	c:%c	d:%lf	p:%s	arr:%s
", 
       hua.a,hua.c,hua.d,hua.Jacy.p,hua.Jacy.arr); 
// 變形 3 [ 推薦使用 ]  
typedefstructCuiHua { 

      intnum; 
      char*name; 
      charclass[32]; 
}stu_info,*stu_info_p; //使用typedef給結(jié)構(gòu)體取別名 
      //stu_info等同于structCuiHua 
      //stu_info_p等同于structCuiHua* 

intmain(intargc,charconst*argv[]) 
{ 
    stu_infoa;//定義一個(gè)普通的結(jié)構(gòu)體變量 
    a.num=100; 
    a.name=calloc(1,32); 
    strncpy(a.name,"張全蛋",32); //注意拷貝之前必須分配空間給a.name。
    strncpy(a.class,"GZ206666",32); 
    printf("Num:%d	Name:%s	Class:%s
",a.num,a.name,a.class);
    stu_info_pc=calloc(1,sizeof(stu_info));//定義一個(gè)結(jié)構(gòu)體指針變量 
    (*c).num=200; 
    c->name=calloc(1,32); 
    strncpy(c->name,"張半蛋",32); 
    strncpy(c->class,"GZ206667",32); 
    printf("Num:%d	Name:%s	Class:%s
",c->num,c->name,c->class); 
    return0;
} 

CPU 字長(zhǎng)

?指CPU一次性從內(nèi)存中獲取的數(shù)據(jù)大小。32位cpu一次性處理4字節(jié)2進(jìn)制數(shù),64位計(jì)算機(jī)一次性處理8字節(jié)2進(jìn)制數(shù)。

地址對(duì)齊

?CPU字長(zhǎng)確定之后就可以確定我們的CPU每一次在讀、寫(xiě)內(nèi)存的時(shí)候都是確定大小 ,假設(shè)是32位系統(tǒng),那么每一次讀、寫(xiě)內(nèi)存時(shí) ,都是按照4字節(jié)進(jìn)行操作。
如果是沒(méi)有對(duì)齊的情況下,需要讀取8字節(jié)則最多需要讀取3次才可以把所有數(shù)據(jù)讀取完整。如果是對(duì)齊的情況下只需要讀取兩次。

?所以,如果地址沒(méi)有對(duì)齊CPU在操作時(shí)需要浪費(fèi)更多的時(shí)間,可以犧牲內(nèi)存來(lái)提高效率。但也可以犧牲效率來(lái)提高內(nèi)存。

普通變量的M值

?變量的地址值,能被M值整除。

char c ; // 大小 1 字節(jié) , M值 1 
short s ; // 大小 2 字節(jié) , M值 2 
int i ; // 大小 4字節(jié) , M值 4 
double d ;// 大小 4字節(jié) , M值 4 
printf("a:%p
",&a); 
printf("s:%p
",&s);
printf("i:%p
",&i); 
printf("d:%p
",&d);
```

注意:
1.如果變量的尺寸小于 4 字節(jié),那么該變量的 m 值等于變量的長(zhǎng)度;
2.如果變量的尺寸大于等于 4 字節(jié),則一律按 4 字節(jié)對(duì)齊;
3.如果變量的 m 值被人為調(diào)整過(guò),則以調(diào)整后的 m 值為準(zhǔn)。

手動(dòng)干預(yù)M值:

char c __attribute__((aligned(4))) ; // 手動(dòng)干預(yù)一般只能往大的設(shè)置不可以設(shè)置更小 

注意:
1.__attribute__是GNU特定的語(yǔ)法,屬于C語(yǔ)言的拓展
2.__attribute__寫(xiě)法注意 左右兩邊都是兩個(gè)下劃線右邊有兩組括號(hào) (( ))
3.((aligned(4)))一個(gè)變量M值只能被提高不可以降低

結(jié)構(gòu)體的M值

?結(jié)構(gòu)體的M值取決于結(jié)構(gòu)體中最大成員的M值。結(jié)構(gòu)體的對(duì)長(zhǎng)字節(jié)取決于,結(jié)構(gòu)體中最長(zhǎng)字節(jié)和系統(tǒng)字長(zhǎng)中最短的那個(gè)。

typedefstructCuiHua { 

      intnum; //4 
      charc1;//1 
      char*name; //8 
      charc2;//1 
      charc3;//1 
      double8;//8 
      charc4;//1 
}stu,*p_stu;

intmain(intargc,charconst*argv[])
{ 
      stua; 
      printf("&a:%p
",&a); 
      printf("&a.num:%p
",&a.num); 
      printf("&a.name:%p
",&a.name); 
      printf("&a.c1:%p
",&a.c1); 
      printf("&a.c2:%p
",&a.c2); 
      printf("&a.c3:%p
",&a.c3); 
      printf("&a.c4:%p
",&a.c4); 
      printf("&a.d:%p
",&a.d); 
      printf("sizeof(a):%ld
",sizeof(a)); //輸出40
      return0; 
    } 

如上圖所示,在64位系統(tǒng)下結(jié)構(gòu)體a占40個(gè)大小,結(jié)構(gòu)體最大M為8,字體字長(zhǎng)也為8,所以結(jié)構(gòu)體M為8。安裝結(jié)構(gòu)體中變量定義的方式排序,
每個(gè)變量的M值,必須能被變量的起始地址整除,所以得到如上圖所示的存儲(chǔ)方式,每種顏色代表一個(gè)變量。

可移植性

?同樣一份代碼在不同的操作系統(tǒng)下(系統(tǒng)位數(shù)),需要考慮可移植性的問(wèn)題,如數(shù)據(jù)尺寸的變化,存儲(chǔ)位置的變換

//方法1 統(tǒng)一壓實(shí)結(jié)構(gòu)體成員:
structCuiHua { 

      intnum;//4 
      charc1;//1 
      char*name; //8
      charc2; //1 
      charc3; //1 
      doubled; //8 
      charc4;  //1 
}__attribute__((packed)); //把結(jié)構(gòu)體進(jìn)行壓實(shí),不考慮按照順序排列了,能多擠就多擠,當(dāng)然變量的起始地址還是會(huì)被M整除,該結(jié)構(gòu)體大小為24

structCuiHua { 

      intnum __attribute__((aligned(4)));//4 
      char  c1  __attribute__((aligned(1)));//1 
      char*name __attribute__((aligned(8)));//4 
      charc2 __attribute__((aligned(1)));//1 
      charc3 __attribute__((aligned(1)));//1 
      doubled __attribute__((aligned(8)));//4 
}

總結(jié)

以上是生活随笔為你收集整理的结构体的概念的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。

如果覺(jué)得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。