<kbd id="afajh"><form id="afajh"></form></kbd>
<strong id="afajh"><dl id="afajh"></dl></strong>
    <del id="afajh"><form id="afajh"></form></del>
        1. <th id="afajh"><progress id="afajh"></progress></th>
          <b id="afajh"><abbr id="afajh"></abbr></b>
          <th id="afajh"><progress id="afajh"></progress></th>

          全面復(fù)盤C語(yǔ)言struct 與 union

          共 26972字,需瀏覽 54分鐘

           ·

          2023-10-15 18:48

             
             
              關(guān)注、星標(biāo)公眾號(hào),直達(dá)精彩內(nèi)容


          struct 結(jié)構(gòu)體

          struct即結(jié)構(gòu)體,C程序中經(jīng)常需要用相關(guān)的不同類型的數(shù)據(jù)來(lái)描述一個(gè)數(shù)據(jù)對(duì)象。例如,描述學(xué)生的綜合信息時(shí),需要使用學(xué)生的學(xué)號(hào)、姓名、性別等不同類型的數(shù)據(jù)時(shí),像這種數(shù)據(jù)類型總是在一起出現(xiàn),那么我們不如把這些變量裝入同一個(gè)“文件夾”中,這時(shí)用的關(guān)鍵字struct聲明的一種數(shù)據(jù)類型就是表示這個(gè)“文件夾”的使用。那么在說(shuō)明和使用之前必須先定義它,也就是構(gòu)造它。如同在說(shuō)明和調(diào)用函數(shù)之前要先定義一樣。


          結(jié)構(gòu)體是一種集合,它里面包含了多個(gè)變量或數(shù)組,它們的類型可以相同,也可以不同,每個(gè)這樣的變量或數(shù)組都稱為結(jié)構(gòu)體的成員,結(jié)構(gòu)體也是一種數(shù)據(jù)類型,它由程序員自己定義,可以包含多個(gè)其他類型的數(shù)據(jù),成員又稱為成員變量,它是結(jié)構(gòu)體所包含的若干個(gè)基本的結(jié)構(gòu)類型,必須用“{}”括起來(lái),并且要以分號(hào)結(jié)束,每個(gè)成員應(yīng)表明具體的數(shù)據(jù)類型,成員一般用名字訪問(wèn)。結(jié)構(gòu)體和數(shù)組類似,也是一組數(shù)據(jù)的集合,整體使用沒(méi)有太大的意義。數(shù)組使用下標(biāo)[ ]獲訪問(wèn)元素,結(jié)構(gòu)體使用點(diǎn)號(hào).訪問(wèn)單個(gè)成員。通過(guò)這種方式可以獲取成員的值,也可以給成員賦值

          數(shù)組:a[0]=10;  結(jié)構(gòu)體:today.day  (指針結(jié)構(gòu)體用->訪問(wèn))結(jié)構(gòu)體的成員可以包含其他結(jié)構(gòu)體,也可以包含指向自己結(jié)構(gòu)體類型的指針,而通常這種指針的應(yīng)用是為了實(shí)現(xiàn)一些更高級(jí)的數(shù)據(jù)結(jié)構(gòu)如鏈表和樹(shù)等。

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

          struct關(guān)鍵字+結(jié)構(gòu)體的標(biāo)志名+大括號(hào)里邊是成員+}后面的聲明此結(jié)構(gòu)變量+末尾分號(hào),一般有這些:

          struct week{定義一  int x;  char y;   };  struct week p1,p2;  //聲明變量p1,p2,里邊都是week的值          //里邊有x和y的值  //用.訪問(wèn) :p1.x  p2.x// p1.y, p2.y
          struct{定義二 int x; char y; }p1,p2;//在這里聲明變量//p1和p2都是一種無(wú)名結(jié)構(gòu),// 里邊有X和y 訪問(wèn)一樣用.
          struct week {定義三 int x; int y;}p1,p2;//常用的一種結(jié)構(gòu)定義聲明形式
          對(duì)于第一和第三種形式,都聲明了結(jié)構(gòu)名week,但是第二種沒(méi)有聲明結(jié)構(gòu)名,只是定義了兩個(gè)結(jié)構(gòu)變量,這種叫無(wú)名結(jié)構(gòu)
          無(wú)名結(jié)構(gòu): 可以定義無(wú)名結(jié)構(gòu)體類型的變量。編譯器對(duì)無(wú)名結(jié)構(gòu)體的處理是隨機(jī)生成一個(gè)不重復(fù)的變量名。無(wú)名結(jié)構(gòu)的定義方式就是定義無(wú)名結(jié)構(gòu)體時(shí)必須定義該結(jié)構(gòu)體類型的至少一個(gè)變量。
          優(yōu)點(diǎn):無(wú)名結(jié)構(gòu)體的妙用就是可以避免相同類型的結(jié)構(gòu)體的重復(fù)定義,這樣可以對(duì)每一個(gè)具體類型的隊(duì)列都可以定義一個(gè)結(jié)構(gòu)體來(lái)管理該隊(duì)列的頭尾指針,即使定義多個(gè)相同具體類型的隊(duì)列也不會(huì)引發(fā)重復(fù)定義的編譯錯(cuò)誤。這樣定義了兩個(gè)隊(duì)列,其元素類型均為int類型,同時(shí)各得到了一個(gè)維護(hù)隊(duì)列頭尾指針的結(jié)構(gòu)體
          缺點(diǎn):這里定義了一個(gè)無(wú)名的結(jié)構(gòu)體,同時(shí)聲明了三個(gè)此種類型的變量。但是,因?yàn)闆](méi)有名字,我們?cè)谶@句之后,無(wú)法內(nèi)再定義與那三種變量相同類型的變量了。除非你再容次去定義一個(gè)這樣的相同的結(jié)構(gòu)體類型。還有一個(gè)重要的原因就是沒(méi)有辦法在其他位置定義我們所需要的結(jié)構(gòu)體變量,每次需要新定義結(jié)構(gòu)體變量的時(shí)候都必須要找到最開(kāi)始結(jié)構(gòu)體代碼書(shū)寫(xiě)的位置才能定義新的結(jié)構(gòu)體 所以實(shí)際編程中無(wú)名結(jié)構(gòu)并不常用

          注意:

          1、結(jié)構(gòu)體本身并不會(huì)被作為數(shù)據(jù)而開(kāi)辟內(nèi)存,真正作為數(shù)據(jù)而在內(nèi)存中存儲(chǔ)的是這種結(jié)構(gòu)體所定義的變量。

          2、先聲明結(jié)構(gòu)體類型,再定義該類型的變量,聲明結(jié)構(gòu)體類型,不分配空間定義結(jié)構(gòu)體類型變量,就要分配內(nèi)存空間

          3、量使用占為少的類型,如,在可能的時(shí)候使用short代替int,按數(shù)據(jù)類型本身占用的位置從大到小排

          4、除了可以對(duì)成員進(jìn)行逐一賦值,也可以在定義時(shí)整體賦值:p1={struct week}{5,10}; 相當(dāng)于 p1.x=5,p1.y=10;

          p1=p2 表示 p1.x=p2.x ,  p1.y=p2.y; 不過(guò)整體賦值僅限于定義結(jié)構(gòu)體變量的時(shí)候,在使用過(guò)程中只能對(duì)成員逐一賦值

          5、結(jié)構(gòu)體變量不能相加,相減,也不能相互乘除,但結(jié)構(gòu)體可以相互賦值,也就是說(shuō),可以將一個(gè)結(jié)構(gòu)體變量賦值給另一個(gè)結(jié)構(gòu)體變量。但是前提是這兩個(gè)結(jié)構(gòu)體變量的結(jié)構(gòu)體類型必須相同

          結(jié)構(gòu)體的運(yùn)算:要訪問(wèn)整個(gè)結(jié)構(gòu),直接用結(jié)構(gòu)變量的名字,對(duì)于整個(gè)結(jié)構(gòu),可以做賦值,取地址,也可以傳遞給函數(shù)參數(shù)


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

          嵌套的結(jié)構(gòu)體:

          struct week{int x;int y;strcut week at;//在結(jié)構(gòu)體又定義了名為at的一個(gè)和week同樣參數(shù)的結(jié)構(gòu)體變量        //其中可以用.運(yùn)算符訪問(wèn)  see.at.x see.at.y}see;但是其實(shí)這樣的方式是不建議(非法)的,因?yàn)檫@種聲明實(shí)際上是一個(gè)無(wú)限循環(huán),成員at是一個(gè)結(jié)構(gòu)體,at的內(nèi)部還會(huì)有成員是結(jié)構(gòu)體,依次下去,無(wú)線循環(huán)。在分配內(nèi)存的時(shí)候,由于無(wú)限嵌套,也無(wú)法確定這個(gè)結(jié)構(gòu)體的長(zhǎng)度,所以這種方式是非法的正確的方式是使用《結(jié)構(gòu)體指針》,因?yàn)橹羔樀拈L(zhǎng)度是確定的:
          struct week{int x;int y;strcut week *at;//在結(jié)構(gòu)體內(nèi)定義了一個(gè)指向和week一樣類型的結(jié)構(gòu)指針}see; 但是注意用指針訪問(wèn)時(shí)要用->運(yùn)算符 see.at->x

          結(jié)構(gòu)體相互引用:

          一個(gè)結(jié)構(gòu)體A中包含一個(gè)或多個(gè)與結(jié)構(gòu)體B相關(guān)的成員, 且結(jié)構(gòu)體B中也包含一個(gè)或多個(gè)與結(jié)構(gòu)體A相關(guān)的成員稱為結(jié)構(gòu)體的互引用.

          但是要注意: 如果已經(jīng)定義了兩個(gè)結(jié)構(gòu)A和B ,在定義結(jié)構(gòu)體A的成員b時(shí),結(jié)構(gòu)體B對(duì)A還未可見(jiàn),故此時(shí)編譯器會(huì)報(bào)數(shù)據(jù)類型B未定義

          解決的辦法是使用不完整聲明:

          strcut A;//不完整聲明strcut B;//不完整聲明strcut _A{               strcut _B{int x;          int x;int y;                 int y;struct _B a;        struct _A b;  //在結(jié)構(gòu)B中定義了一個(gè)名為b的和A結(jié)構(gòu)一樣類型的結(jié)構(gòu)變量                 //其中可以用點(diǎn)訪問(wèn) A.a.x   B.b.x}A;                      }B;//但是注意這種方式犯了一個(gè)和上面第一個(gè)嵌套結(jié)構(gòu)的錯(cuò)誤,就是結(jié)構(gòu)體A和B都是直接包含了對(duì)方,正確的用法還是使用指針:strcut _A{               strcut _B{int x;          int x;int y;                 int y;struct _B *a;      struct _A *b;  //在結(jié)構(gòu)B中定義了一個(gè)名為b的和A結(jié)構(gòu)一樣類型的結(jié)構(gòu)指針                       //其中指針要用->訪問(wèn) A.a->x   B.b->x}A;                                 }B;  //但是注意這種方式犯了一個(gè)和上面第一個(gè)嵌套結(jié)構(gòu)的錯(cuò)誤,就是結(jié)構(gòu)體A和B都是直接包含了對(duì)方,正確的用法還是使用指針:strcut _A{               strcut _B{int x;              int x;int y;                 int y;struct _B *a;       struct _A *b;  //在結(jié)構(gòu)B中定義了一個(gè)名為b的和A結(jié)構(gòu)一樣類型的結(jié)構(gòu)指針                 //其中指針要用->訪問(wèn) A.a->x   B.b->x}A;                                }B;//所以使用互引用要注意:至少有一個(gè)結(jié)構(gòu)必須在另一個(gè)結(jié)構(gòu)體中以指針的形式被引用。

          結(jié)構(gòu)體函數(shù)與函數(shù)參數(shù)

          結(jié)構(gòu)體做函數(shù)形參:

          整個(gè)結(jié)構(gòu)可以作為參數(shù)的值傳入函數(shù),這時(shí)候是在函數(shù)內(nèi)新建一個(gè)結(jié)構(gòu)變量,并復(fù)制調(diào)用者結(jié)構(gòu)的值,也可以返回一個(gè)值,這和數(shù)組完全不同

          用結(jié)構(gòu)體變量作實(shí)參時(shí),采取的也是“值傳遞”方式,將  結(jié)構(gòu)體變量所占的內(nèi)存單元的內(nèi)容(結(jié)構(gòu)體變量成員列表)  全部順序傳遞給形參,這里形參也得是結(jié)構(gòu)體變量。

          #include<stdio.h>typedef struct _node {
          int n; char a[100];
          }NODE;
          void add(NODE a);//這種形式只是用來(lái)做值的傳遞
          int main(void) { //以傳值方式傳遞結(jié)構(gòu)需要對(duì)整個(gè)結(jié)構(gòu)做一份拷貝 NODE t; scanf("%d %d", &t.a[0], &t.n);//輸入1 3
          printf("1-%d %d\n",t.a[0],t.n);//輸出 1 3
          add(t); printf("3-%d %d\n", t.a[0], t.n);//輸出1 3
          //也就是說(shuō)在add函數(shù)里邊做修改根本就影響不了主函數(shù)這邊的值}
          void add(NODE a) {
          a.a[0] = 100;//在這里能接受到NODE結(jié)構(gòu)里邊的成員 a.n = 666;
          printf("2-%d %d\n", a.a[0], a.n);//輸出100 666
          } ****//解決辦法是用指針(也是經(jīng)常用的方式):****#include<stdio.h>typedef struct _node {
          int n; char a[100];
          }NODE;
          int add(NODE a);//這種形式只是用來(lái)做值的傳遞
          int main(void) { //以傳值方式傳遞結(jié)構(gòu)需要對(duì)整個(gè)結(jié)構(gòu)做一份拷貝 NODE t; scanf("%d %d", &t.a[0], &t.n);//輸入1 3
          printf("1-%d %d\n",t.a[0],t.n);//輸出 1 3

          add(&t);//這里傳進(jìn)去的是t的地址 printf("3-%d %d\n", t.a[0], t.n);//輸出100 666//傳進(jìn)去的是地址,所以就可以達(dá)到訪問(wèn)同一個(gè)變量的操作}
          int add(NODE *) {//定義一個(gè)結(jié)構(gòu)指針
          a.a[0] = 100;//在這里能接受到NODE結(jié)構(gòu)里邊的成員 a.n = 666;
          printf("2-%d %d\n", a.a[0], a.n);//輸出100 666 return a;//這里返回的是指針 所以能達(dá)到訪問(wèn)主函數(shù)里邊調(diào)用的值 //使用指針才可以用返回值}//常用的方式

          另一種做法

          結(jié)構(gòu)體做函數(shù):

          /*上面的第一個(gè)的方案,把一個(gè)結(jié)構(gòu)傳入了函數(shù),然后在函數(shù)中操作,但是沒(méi)有返回回去問(wèn)題在于傳入函數(shù)的是外面那個(gè)結(jié)構(gòu)的克隆體,而不是指針,傳入結(jié)構(gòu)和傳入數(shù)組是不同的,解決辦法是在這個(gè)輸入函數(shù)中,在里邊創(chuàng)建一個(gè)臨時(shí)的結(jié)構(gòu)變量,然后把這個(gè)結(jié)構(gòu)返回給調(diào)用者*/#include<stdio.h>typedef struct _node {  int x;  int y;}NODE;struct _node add();//定義結(jié)構(gòu)類型的函數(shù)int main(void) {
          NODE a; a.x = 0; a.y = 0; printf("1-%d %d\n", a.x, a.y);// 0 0
          a = add();//函數(shù)調(diào)用 /把n的值又返回到a
          printf("3-%d %d\n", a.x, a.y);//所以在這里的時(shí)候值已經(jīng)被改變 return 0;}
          struct _node add() {
          NODE n; scanf("%d", &n.x);//輸入1 3
          scanf("%d", &n.y);
          printf("2-%d %d\n", n.x, n.y);//在這里的時(shí)候賦值就成功了
          //return n;//把n的值帶回出去}//這種方法也能達(dá)到“改變"的效果,但是往往開(kāi)銷內(nèi)存較大,所以一般情況都是使用指針比較方便

            用結(jié)構(gòu)體變量名作參數(shù),這種傳遞方式是單向的,如果在執(zhí)行被調(diào)函數(shù)期間改變了形參(也是結(jié)構(gòu)體變量)的值,該值不能返回主調(diào)函數(shù),這往往造成使用上的不便,因此一般少用這種方法。

          和本地變量一樣。在函數(shù)內(nèi)部聲明的結(jié)構(gòu)只能在函數(shù)內(nèi)部使用,所以通常在函數(shù)外部聲明一個(gè)結(jié)構(gòu)類型的,這樣就可以被多個(gè)函數(shù)所使用

          //結(jié)構(gòu)做函數(shù)參數(shù)例子 (輸入今天計(jì)算明天)#include<stdio.h>#include<stdbool.h>//利用布爾數(shù)據(jù)類型struct date {  int year;  int month;  int day;
          };
          bool If(struct date p);//判斷是否是閏年int number(struct date c);//判斷是否是此月最后一天
          int main(void) {
          struct date today,tomorrow; printf("年-月-日\(chéng)n"); scanf("%d %d %d", &today.year, &today.month, &today.day);
          //前面兩個(gè)判斷 是否此月最后一天 是否此年此月最后一天 if (today.day==number(today)&&today.month!=12) {//首月1號(hào) tomorrow.day = 1; tomorrow.month =today.month+1; tomorrow.year = today.year; } else if (today.day == number(today) && today.month == 12) {//下一年 tomorrow.day = 1; tomorrow.month = 1; tomorrow.year =today.year+1; } else { tomorrow.day =today.day+1; tomorrow.month = today.month; tomorrow.year = today.year; }
          printf("明天是%d-%d-%d\n", tomorrow.year, tomorrow.month, tomorrow.day); return 0;}
          int number(struct date c)//這里的形參接收的today結(jié)構(gòu)體數(shù)據(jù){ int day; const int a[12] = { 31,28,31,30,31,30,31,31,30,31,30,31 };//這個(gè)月最大的天數(shù)
          if (c.month==22&&If(c)) {//查看是否是二月并且是潤(rùn)年 day = 29;//是潤(rùn)年 } else {
          day = a[c.month - 1]; }
          return day;}
          bool If(struct date p) {//這里的形參接收的today結(jié)構(gòu)體數(shù)據(jù) //潤(rùn)年的特點(diǎn),能被4整除,但不能被100整數(shù),能被100整除,但是不能被400整除 if (p.year % 4 == 0 && p.year / 100 != 0 || p.year % 400 == 0) { return true; } else { return false; }}
          //結(jié)構(gòu)體做函數(shù)例子 (計(jì)算下一秒)#include<stdio.h>struct time {  int hour;  int minute;  int second;};
          struct time times(struct time now);//利用結(jié)構(gòu)做函數(shù)返回值,形參也是使用結(jié)構(gòu)體做為傳值
          int main(void) { struct time nows[5] = { {11,50,20},{13,25,59},{12,59,59},{23,59,59},{00,00,00}, };
          int i; for (i = 0; i < 5; i++) { printf("時(shí)間是 %d:%d:%d\n", nows[i].hour, nows[i].minute, nows[i].second);
          nows[i] = times(nows[i]);
          printf("下一秒是 %d:%d:%d\n", nows[i].hour, nows[i].minute, nows[i].second); }
          return 0;
          }
          struct time times(struct time now) {
          now.second++; if (now.second == 60) {//60秒 now.minute++; now.second = 0;
          if (now.minute == 60)//60分 { now.hour++; now.minute = 0; now.second = 0;
          if (now.hour == 24) {//零點(diǎn) now.hour=0; now.minute = 0; now.second = 0; } } }
          return now;//返回類型必須也函數(shù)類型一致,換句話說(shuō)只有結(jié)構(gòu)體類型才能返回結(jié)構(gòu)體類型
          }

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

          結(jié)構(gòu)體數(shù)組,是指數(shù)組中的每個(gè)元素都是一個(gè)結(jié)構(gòu)體。在實(shí)際應(yīng)用中,C語(yǔ)言結(jié)構(gòu)體數(shù)組常被用來(lái)表示一個(gè)擁有相同數(shù)據(jù)結(jié)構(gòu)的群體,比如一個(gè)班的學(xué)生、一個(gè)車間的職工等。結(jié)構(gòu)體可以存儲(chǔ)不同的數(shù)據(jù)類型,將他們互相聯(lián)系起來(lái)。結(jié)構(gòu)體數(shù)組可以連續(xù)存儲(chǔ)多個(gè)結(jié)構(gòu)體,和數(shù)組作用相似。比如想定義同一個(gè)最小外接矩形的四個(gè)坐標(biāo)值,并給予這個(gè)矩形一個(gè)特征編號(hào)。當(dāng)需要存儲(chǔ)多個(gè)最小外接矩形的信息時(shí),就需要?jiǎng)討B(tài)申請(qǐng)一個(gè)結(jié)構(gòu)體數(shù)組

          定義結(jié)構(gòu)體數(shù)組的方法很簡(jiǎn)單,同定義結(jié)構(gòu)體變量是一樣的,只不過(guò)將變量改成數(shù)組。或者說(shuō)同前面介紹的普通數(shù)組的定義是一模一樣的:struct student  tp[10]; 這就定義了一個(gè)結(jié)構(gòu)體數(shù)組,共有 10 個(gè)元素,每個(gè)元素都是一個(gè)結(jié)構(gòu)體變量,都包含所有的結(jié)構(gòu)體成員。

          結(jié)構(gòu)體數(shù)組的初始化與前面講的數(shù)值型數(shù)組的初始化也是一樣的,數(shù)值型數(shù)組初始化的方法和需要注意的問(wèn)題在結(jié)構(gòu)體數(shù)組的初始化中同樣適用,因?yàn)椴还苁菙?shù)值型數(shù)組還是結(jié)構(gòu)體數(shù)組都是數(shù)組。

          //例子:  //尋找學(xué)生中 學(xué)號(hào)最大的# include <stdio.h># include <string.h>
          struct STU{ char name[20]; int age; char sex[20]; char num[20];
          };
          void OutputSTU(struct STU stu[]); //函數(shù)聲明, 該函數(shù)的功能是輸出成績(jī)最大的學(xué)生信息
          int main(void){ int i; struct STU stu[5];
          for (i = 0; i < 2; ++i) { printf("請(qǐng)按照名字、年齡、性別、學(xué)號(hào)(1-9數(shù)字)輸入第%d個(gè)學(xué)生的信息:", i + 1);
          scanf("%s %d %s %s", stu[i].name, &stu[i].age, stu[i].sex, stu[i].num);/*%c前面要加空格, 不然輸入時(shí)會(huì)將空格賦給%c*/ }
          OutputSTU(stu);
          return 0;}
          void OutputSTU(struct STU stu[]){ struct STU stumax = stu[0];//讓臨時(shí)結(jié)構(gòu)stumax保存第一個(gè)學(xué)生的信息
          int j; for (j = 1; j < 2; ++j)//第一個(gè)學(xué)生依次和后面的學(xué)生比較 { if (strcmp(stumax.num, stu[j].num) < 0) //strcmp函數(shù)的使用 s1>s2:1 s1<s2:-1 { stumax = stu[j];//讓臨時(shí)結(jié)構(gòu)保存那個(gè)學(xué)生的信息 } }
          printf("學(xué)生姓名:%s 學(xué)生年齡:%d 學(xué)生性別:%s 學(xué)生分?jǐn)?shù):%s\n", stumax.name, stumax.age, stumax.sex, stumax.num);
          }

          結(jié)構(gòu)體指針

          和數(shù)組不同,結(jié)構(gòu)變量的名字并不是結(jié)構(gòu)變量的地址,必須使用&運(yùn)算符  strcut node *tp=&nb;  指針一般用->訪問(wèn)結(jié)構(gòu)體里邊的成員

          指針變量非常靈活方便,可以指向任一類型的變量    ,若定義指針變量指向結(jié)構(gòu)體類型變量,則可以通過(guò)指針來(lái)引用結(jié)構(gòu)體類型變量。

          #include<stdio.h>struct node{int x;int y;}my;int main(void) {  struct node *p = &my;//定義了一個(gè)指針p指向了my的結(jié)構(gòu)體
          p->x = 11;//這是一種訪問(wèn)方式(常用的方式) (*p).x = 12;//這是第二種方式, printf("%d", p->x);//輸出是12
          }以下 2 種形式是等價(jià)的:(*指針變量).成員名。指針變量->成員名。其中第 2 種方式很重要,通常都是使用這種方式,另外兩種方式用得不多。后面講鏈表的時(shí)候用的也都是第 3 種方式。

          這里說(shuō)明:結(jié)構(gòu)體和結(jié)構(gòu)體變量是兩個(gè)不同的概念:結(jié)構(gòu)體是一種數(shù)據(jù)類型,是一種創(chuàng)建變量的模板,編譯器不會(huì)為它分配內(nèi)存空間,就像 int、float、char 這些關(guān)鍵字本身不占用內(nèi)存一樣;結(jié)構(gòu)體變量才包含實(shí)實(shí)在在的數(shù)據(jù),才需要內(nèi)存來(lái)存儲(chǔ)。所以用一個(gè)結(jié)構(gòu)體去取一個(gè)結(jié)構(gòu)體名的地址,這種寫(xiě)法是錯(cuò)誤的,也不能將它賦值給其他變量。

          #include<stdio.h>struct point {  int x;  int y;};struct point *gt(struct point*p);//結(jié)構(gòu)指針函數(shù)
          void print(const struct point *p);//結(jié)構(gòu)指針
          void out(struct point p);//普通的結(jié)構(gòu)體做函數(shù)參數(shù)
          int main(void) { struct point y = { 0,0 };//以point結(jié)構(gòu)定義一個(gè)y的結(jié)構(gòu)變量
          //以下三種調(diào)用 等價(jià) //注意gt是一個(gè)結(jié)構(gòu)體的指針函數(shù) gt(&y); //這是一個(gè)函數(shù)的返回結(jié)果函數(shù) //取y結(jié)構(gòu)的地址傳入函數(shù) out(y); out(*gt(&y)); // (里邊)的都是做為參數(shù) *gt(&y)做為指針?lè)祷刂? 這個(gè)函數(shù)它的返回用指針表示 print(gt(&y)); //gt(&y)是一個(gè)返回值 這樣表示的是利用gt函數(shù)的返回值在print函數(shù)里邊操作
          //*get(&y) = (struct point){ 1,2 }; //這也可以做的}
          struct point* gt(struct point*p) {// *p要的是&y的地址 scanf("%d", &p->x); scanf("%d", &p->y); printf("a=%d,%d \n", p->x, p->y);//用->來(lái)訪問(wèn)指針結(jié)構(gòu)里邊的成員
          return p;// 用完指針后 返回指針}void out(struct point p) { printf("b=%d,%d\n", p.x, p.y);}
          void print(const struct point *p) {//加上const表示不再改動(dòng)參數(shù) printf("c=%d,%d\n", p->x, p->y);}

          指向結(jié)構(gòu)體數(shù)組的指針:

          在之前講數(shù)值型數(shù)組的時(shí)候可以將數(shù)組名賦給一個(gè)指針變量,從而使該指針變量指向數(shù)組的首地址,然后用指針訪問(wèn)數(shù)組的元素。結(jié)構(gòu)體數(shù)組也是數(shù)組,所以同樣可以這么做。

          我們知道,結(jié)構(gòu)體數(shù)組的每一個(gè)元素都是一個(gè)結(jié)構(gòu)體變量。如果定義一個(gè)結(jié)構(gòu)體指針變量并把結(jié)構(gòu)體數(shù)組的數(shù)組名賦給這個(gè)指針變量的話,就意味著將結(jié)構(gòu)體數(shù)組的第一個(gè)元素,即第一個(gè)結(jié)構(gòu)體變量的地址,也即第一個(gè)結(jié)構(gòu)變量中的第一個(gè)成員的地址賦給了這個(gè)指針變量

          # include <stdio.h>struct qt{  char name[5];  int age;  char sex[5];  double scroe;};int main(void){    //定義了一個(gè)student的結(jié)構(gòu)數(shù)組  struct qt student[5] = { {"李青", 20, "男", 99}, {"黃歡", 20,  "女", 80}, {"七七", 23, "男", 95} };  struct qt *p = student;  int i;  for (i = 0; i < 5; i++) {
          printf("%s ", p->name);//利用->可訪問(wèn)成員(訪問(wèn)意味著可以讀寫(xiě)) printf("%d ", p->age); printf("%s ", p->sex); printf("%f ", p->scroe); } return 0;}當(dāng)結(jié)構(gòu)體指針變量指向一個(gè)結(jié)構(gòu)體變量數(shù)組的時(shí)候,此時(shí)指針變量的值就是結(jié)構(gòu)體數(shù)組的首地址,此時(shí)指針變量 p 就指向了結(jié)構(gòu)體數(shù)組的第一個(gè)元素,即指向 student[0]。我們知道,當(dāng)一個(gè)指針指向一個(gè)數(shù)組后,指針就可以通過(guò)移動(dòng)的方式指向數(shù)組的其他元素。這個(gè)原則對(duì)結(jié)構(gòu)體數(shù)組和結(jié)構(gòu)體指針同樣適用,所以 p + 1 就指向 student[1] 的首地址;p + 2 就指向 student[2] 的首地址……所以只要利用 for 循環(huán),指針就能一個(gè)個(gè)地指向結(jié)構(gòu)體數(shù)組元素。
          同樣需要注意的是,要將一個(gè)結(jié)構(gòu)體數(shù)組名賦給一個(gè)結(jié)構(gòu)體指針變量,那么它們的結(jié)構(gòu)體類型必須相同。

          typedef 別名

          typedef是在編程語(yǔ)言中用來(lái)為復(fù)雜的聲明定義簡(jiǎn)單的別名,新的名字是某種類型的別名,這樣做改善了程序的可讀性,它與宏定義有些差異。它本身是一種存儲(chǔ)類的關(guān)鍵字,與auto、extern、mutable、static、register等關(guān)鍵字不能出現(xiàn)在同一個(gè)表達(dá)式中。

          typedef為C語(yǔ)言的關(guān)鍵字,功能是用來(lái)聲明一個(gè)已有的數(shù)據(jù)類型的新名字,比如 typedef int last ;  這就使得last成為 int 類型的別名  這樣last這個(gè)名字就可以代替int出現(xiàn)在變量定義和參數(shù)聲明的地方了

          typedef也有一個(gè)特別的長(zhǎng)處:它符合范圍規(guī)則,使用typedef定義的變量類型其作用范圍限制在所定義的函數(shù)或者文件內(nèi)(取決于此變量定義的位置),而宏定義則沒(méi)有這種特性。

          typedef & 復(fù)雜的變量聲明理解復(fù)雜聲明可用的“右左法則”:  從變量名看起,先往右,再往左,碰到一個(gè)圓括號(hào)就調(diào)轉(zhuǎn)閱讀的方向;括號(hào)內(nèi)分析完就跳出括號(hào),還是按先右后左的順序,如此循環(huán),直到整個(gè)聲明分析完。舉例:  int (*func)(int *p);  首 先找到變量名func,外面有一對(duì)圓括號(hào),而且左邊是一個(gè)*號(hào),這說(shuō)明func是一個(gè)指針;然后跳出這個(gè)圓括號(hào),先看右邊,又遇到圓括號(hào)(只有函數(shù)后面才跟形參圓括號(hào)),這說(shuō)明 (*func)是一個(gè)函數(shù),所以func是一個(gè)指向這類函數(shù)的指針,即函數(shù)指針,這類函數(shù)具有int*類型的形參,返回值類型是int,此處就是聲明函數(shù)。  int (*func[5])(int *);  func 右邊是一個(gè)[]運(yùn)算符,說(shuō)明func是具有5個(gè)元素的數(shù)組;func的左邊有一個(gè)*,說(shuō)明func的元素是指針(注意這里的*不是修飾func,而是修飾 func[5]的,原因是[]運(yùn)算符優(yōu)先級(jí)比*高,func先跟[]結(jié)合)。跳出這個(gè)括號(hào),看右邊,又遇到圓括號(hào),說(shuō)明func數(shù)組的元素是函數(shù)類型的指 針,它指向的函數(shù)具有int*類型的形參,返回值類型為int
          也可以記住2個(gè)模式:type (*)(....)函數(shù)指針type (*)[]數(shù)組指針

          結(jié)構(gòu)體的內(nèi)存對(duì)齊方式(存儲(chǔ)空間)

          結(jié)構(gòu)體內(nèi)存對(duì)齊:一個(gè)結(jié)構(gòu)體變量定義完之后,其在內(nèi)存中的存儲(chǔ)并不等于其所包含元素的寬度之和,元素是按照定義順序一個(gè)一個(gè)放到內(nèi)存中去的,但并不是緊密排列的。從結(jié)構(gòu)體存儲(chǔ)的首地址開(kāi)始,每個(gè)元素放置到內(nèi)存中時(shí),它都會(huì)認(rèn)為內(nèi)存是按照自己的大小來(lái)劃分的,因此元素放置的位置一定會(huì)在自己寬度的整數(shù)倍上開(kāi)始。

          內(nèi)存對(duì)齊可以大大提升內(nèi)存訪問(wèn)速度,是一種用空間換時(shí)間的方法。內(nèi)存不對(duì)齊會(huì)導(dǎo)致每次讀取數(shù)據(jù)都會(huì)讀取兩次,使得內(nèi)存讀取速度減慢。

          cpu把內(nèi)存當(dāng)成是一塊一塊的,塊的大小可以是2,4,8,16 個(gè)字節(jié),因此CPU在讀取內(nèi)存的時(shí)候是一塊一塊進(jìn)行讀取的,塊的大小稱為內(nèi)存讀取粒度。

          // 內(nèi)存對(duì)齊原則://   1、第一個(gè)成員的首地址為0.//   2、每個(gè)成員的首地址是自身大小的整數(shù)倍//    3、結(jié)構(gòu)體的總大小,為其成員中所含最大類型的整數(shù)倍。
          #include<stdio.h>typedef struct _node { //char t;//1 //int p; //4 //float y;//8//char t 要存放的偏移量為0,滿足對(duì)齊方式,t占用一個(gè)字節(jié),int p要存儲(chǔ)在下一個(gè)可用的地址的偏移量為1.不是sizeof(int)=4的倍數(shù),需要補(bǔ)足3個(gè)字節(jié)才能使偏移量變?yōu)?span id="go7utgvlrp" class="code-snippet__number" style="outline: 0px;">4(使其滿足對(duì)齊方式),因此系統(tǒng)自動(dòng)填充3個(gè)字節(jié)使偏移量增加到4int p放到此位置,占用4個(gè)字節(jié),下一可用的偏移量為8,滿足sizeof(float)=4的對(duì)齊,所以float y直接存放在偏移量為8的位置上,它占用4個(gè)字節(jié) 總共就是 //1+3+4+4=12
          double a;//8 char b;//1 int c;//4//double a的要存放的偏移量為0,滿足對(duì)齊方式直接存儲(chǔ),占用8個(gè)字節(jié),char b要存儲(chǔ)在下一的可用的地址的偏移量為9直接存儲(chǔ),占用字節(jié)為1int c要存儲(chǔ)在下一個(gè)可用的地址的偏移量為99不滿足sizeofint)=4;所以系統(tǒng)會(huì)自動(dòng)分配3的字節(jié)增加到1212滿足對(duì)齊方式,存儲(chǔ)下去c占用4個(gè)字節(jié)。總共就是 //8+1+3+4=16
          }NODE;
          int main(void) { printf("%d ", sizeof(NODE));}

          如果結(jié)構(gòu)體內(nèi)存在長(zhǎng)度大于處理器位數(shù)的元素,那么就以處理器的倍數(shù)為對(duì)齊單位;否則,如果結(jié)構(gòu)體內(nèi)的元素的長(zhǎng)度都小于處理器的倍數(shù)的時(shí)候,便以結(jié)構(gòu)體里面最長(zhǎng)的數(shù)據(jù)元素為對(duì)齊單位。

          另外  結(jié)構(gòu)體的內(nèi)存地址就是它第一個(gè)成員變量的地址  isa永遠(yuǎn)都是結(jié)構(gòu)體中的第一個(gè)成員變量  所以結(jié)構(gòu)體的地址也就是其isa指針的地址

          內(nèi)存對(duì)齊簡(jiǎn)介

          由于內(nèi)存的讀取時(shí)間遠(yuǎn)遠(yuǎn)小于CPU的存儲(chǔ)速度,這里用設(shè)定數(shù)據(jù)結(jié)構(gòu)的對(duì)齊系數(shù),即犧牲空間來(lái)?yè)Q取時(shí)間的思想來(lái)提高CPU的存儲(chǔ)效率。

          內(nèi)存對(duì)齊”應(yīng)該是編譯器的“管轄范圍”。編譯器為程序中的每個(gè)“數(shù)據(jù)單元”安排在適當(dāng)?shù)奈恢蒙稀5荂語(yǔ)言的一個(gè)特點(diǎn)就是太靈活,太強(qiáng)大,它允許你干預(yù)“內(nèi)存對(duì)齊”。如果你想了解更加底層的秘密,“內(nèi)存對(duì)齊”對(duì)你就不應(yīng)該再模糊了。這也是一個(gè)大小端模式的問(wèn)題

          每個(gè)特定平臺(tái)上的編譯器都有自己的默認(rèn)“對(duì)齊系數(shù)”(也叫對(duì)齊模數(shù))。程序員可以通過(guò)預(yù)編譯命令#pragma pack(n)來(lái)改變這一系數(shù),其中的n就是你要指定的“對(duì)齊系數(shù)”。

          規(guī)則:

          1、數(shù)據(jù)成員對(duì)齊規(guī)則:結(jié)構(gòu)(struct)(或聯(lián)合(union))的數(shù)據(jù)成員,第一個(gè)數(shù)據(jù)成員放在offset為0的地方,以后每個(gè)數(shù)據(jù)成員的對(duì)齊按照#pragma pack指定的數(shù)值和這個(gè)數(shù)據(jù)成員自身長(zhǎng)度中,比較小的那個(gè)進(jìn)行

          2、結(jié)構(gòu)(或聯(lián)合)的整體對(duì)齊規(guī)則:在數(shù)據(jù)成員完成各自對(duì)齊之后,結(jié)構(gòu)(或聯(lián)合)本身也要進(jìn)行對(duì)齊,對(duì)齊將按照#pragma pack 指定的數(shù)值和結(jié)構(gòu)(或聯(lián)合) 最大數(shù)據(jù)成員長(zhǎng)度中,比較小的那個(gè)進(jìn)行對(duì)齊。

          3、結(jié)合1、2可推斷:當(dāng)#pragma pack的n值等于或超過(guò)所有數(shù)據(jù)成員長(zhǎng)度的時(shí)候,這個(gè)n值的大小將不產(chǎn)生任何效果。

          #pragmapack(n)  設(shè)定變量以n字節(jié)為對(duì)齊方式:

          作用:指定結(jié)構(gòu)體、聯(lián)合以及類成員

          語(yǔ)法:#pragmapack( [show] | [push | pop] [, identifier], n )

          1,pack提供數(shù)據(jù)聲明級(jí)別的控制,對(duì)定義不起作用;

          2,調(diào)用pack時(shí)不指定參數(shù),n將被設(shè)成默認(rèn)值;

          n:可選參數(shù);指定packing的數(shù)值,以字節(jié)為單位;缺省數(shù)值是8,合法的數(shù)值分別是1、2、4、8、16。

          其他參數(shù)都是可選的可先不了解

          #include<stdio.h>#pragma pack(2)// 值只能填1 2 4 8 16  這里最好是看結(jié)構(gòu)里邊最小的成員 這里是char 所以最好是填1    //但是當(dāng)#pragma pack指定的值等于或者超過(guò)所有數(shù)據(jù)成員長(zhǎng)度的時(shí)候,這個(gè)指定值的大小將不產(chǎn)生任何效果typedef struct _A {
          double x;//4 int y;//4 char p;//1 }NODE;
          //8+4+1+1=14按n為2
          //8+4+1+3=16按n為4以上或者使用系統(tǒng)自動(dòng)對(duì)齊
          #pragma pack(8)//設(shè)定為4字節(jié)對(duì)齊typedef struct test{ char m1; double m4; int m3;
          }NODE2;
          //1+1+4+8=14//按n為2//1+7+8+4=20 不滿足8的倍數(shù) 加4等于24滿足 總:1+7+8+4+4=24

          int main(void) {
          printf("%d\n", sizeof(NODE)); printf("%d", sizeof(NODE2));
          }結(jié)構(gòu)、聯(lián)合或者類的數(shù)據(jù)成員,第一個(gè)放在偏移為0的地方;以后每個(gè)數(shù)據(jù)成員的對(duì)齊,按照#pragma pack指定的數(shù)值和這個(gè)數(shù)據(jù)成員自身長(zhǎng)度兩個(gè)中比較小的那個(gè)進(jìn)行;也就是說(shuō),當(dāng)#pragma pack指定的值等于或者超過(guò)所有數(shù)據(jù)成員長(zhǎng)度的時(shí)候,這個(gè)指定值的大小將不產(chǎn)生任何效果;

          每個(gè)成員分別對(duì)齊,即每個(gè)成員按自己的方式對(duì)齊,并最小化長(zhǎng)度;規(guī)則就是每個(gè)成員按其類型的對(duì)齊參數(shù)(通常是這個(gè)類型的大小)和指定對(duì)齊參數(shù)中較小的一個(gè)對(duì)齊。

          大小端:

          如:int 11 22 33 44在存儲(chǔ)的時(shí)候大端:11 22 33 44   0  1   2  3   低地址----> 高地址
          小端:44 33 22 11 0 1 2 3 低地址----> 高地址大小端的差異在于存放順序不同常見(jiàn)的操作系統(tǒng)是小端,通訊協(xié)議是大端。
          //結(jié)構(gòu)體例子:使用尾插法創(chuàng)建鏈表#include<stdio.h>//單鏈表的創(chuàng)建
          typedef struct _node {
          int nb;//數(shù)值 struct _node *nxte;//定義一個(gè)指向下一個(gè)的節(jié)點(diǎn)的指針
          }NODE;
          typedef struct _link{//利用這個(gè)結(jié)構(gòu)體 封裝 首尾節(jié)點(diǎn)
          NODE *head; NODE *qt;
          }link;
          void add(link *phead, link *qt, int n);//定義函數(shù)將 首尾指針傳入
          int main(void) {
          link head, q;//定義一個(gè)結(jié)構(gòu),連指針都不是的 head.head = q.qt = NULL;//初始化
          int n;
          for (scanf("%d", &n); n != -1; scanf("%d", &n)) { add(&head, &q, n);//將地址 值傳入 }
          NODE *t; t = head.head;//利用臨時(shí)結(jié)構(gòu)將鏈表輸出 for (; t; t = t->nxte) { printf("%d ", t->nb); }
          return 0;}
          //尾插法void add(link *phead, link *qt, int n) {
          NODE *p = (NODE*)malloc(sizeof(NODE));//為新結(jié)點(diǎn)開(kāi)辟空間 p->nb = n; p->nxte = NULL;
          if (phead->head == NULL) {//判斷首結(jié)點(diǎn)是否為空 phead->head = p;//是空的就讓首結(jié)點(diǎn)等于新結(jié)點(diǎn) } else {//不為空時(shí),讓尾結(jié)點(diǎn)依次跑到后面去 qt->qt->nxte = p; }
          qt->qt = p;}

          4、union 共用體(聯(lián)合體)

          在進(jìn)行某些算法的C語(yǔ)言編程的時(shí)候,需要使幾種不同類型的變量存放到同一段內(nèi)存單元中。也就是使用覆蓋技術(shù),幾個(gè)變量互相覆蓋。這種幾個(gè)不同的變量共同占用一段內(nèi)存的結(jié)構(gòu),在C語(yǔ)言中 以關(guān)鍵字union聲明的一種數(shù)據(jù)結(jié)構(gòu),這種被稱作“共用體”類型結(jié)構(gòu),也叫聯(lián)合體。

                  “聯(lián)合”與“結(jié)構(gòu)”有一些相似之處。但兩者有本質(zhì)上的不同。在結(jié)構(gòu)中各成員有各自的內(nèi)存空間,一個(gè)結(jié)構(gòu)體變量的總長(zhǎng)度大于等于各成員長(zhǎng)度之和。而在“聯(lián)合”中,各成員共享一段內(nèi)存空間,一個(gè)聯(lián)合變量的長(zhǎng)度等于各成員中最長(zhǎng)的長(zhǎng)度。注意這里所謂的共享不是指把多個(gè)成員同時(shí)裝入一個(gè)聯(lián)合變量?jī)?nèi),而是指該聯(lián)合變量可被賦予任一成員值,但每次只能賦一種值,賦入新值則沖去舊值,共用體變量中起作用的成員是最后一次存放的成員,在存入一個(gè)新成員后,原有成員就失去作用,共用體變量的地址和它的各成員的地址都是同一地址

          一個(gè)聯(lián)合類型必須經(jīng)過(guò)定義之后,才能把變量說(shuō)明為該聯(lián)合類型:

          聯(lián)合的定義:定義一個(gè)聯(lián)合類型的一般形式為:union [name](聯(lián)合名)   name是可選的{成員表};成員表中含有若干成員,成員的一般形式為: 類型說(shuō)明符 成員名成員名的命名應(yīng)符合標(biāo)識(shí)符的規(guī)定。
          union Data{ int i; double f; char str[20];} data;

          現(xiàn)在 Data所有的成員共享一個(gè)空間,同一時(shí)間只有一個(gè)成員是的值有效的,Data 類型的變量可以存儲(chǔ)一個(gè)整數(shù)、一個(gè)浮點(diǎn)數(shù),或者一個(gè)字符串。這意味著一個(gè)變量(相同的內(nèi)存位置)可以存儲(chǔ)多個(gè)多種類型的數(shù)據(jù)。您可以根據(jù)需要在一個(gè)共用體內(nèi)使用任何內(nèi)置的或者用戶自定義的數(shù)據(jù)類型。共用體占用的內(nèi)存應(yīng)足夠存儲(chǔ)共用體中最大的成員。例如,在上面的實(shí)例中,Data 將占用 20 個(gè)字節(jié)的內(nèi)存空間,因?yàn)樵诟鱾€(gè)成員中,字符串所占用的空間是最大的。

          注意:1、不能把共用體變量作為函數(shù)參數(shù),也不能是函數(shù)帶回共用體變量,但可以使專用指向共用體變量的指針

          2、所有成員占用同一段內(nèi)存,修改一制個(gè)成員會(huì)影響其余所有成員。

          共用體的訪問(wèn):

          共用體訪問(wèn)成員的值時(shí)一般使用.運(yùn)算符,指針時(shí)用->運(yùn)算符(和結(jié)構(gòu)體是一樣的)

          typedef union _node {  int a;  double b;  char c;  union _node *p;
          }NODE;
          int main(void) {
          NODE a;//定義變量 NODE t; a.b;//用.訪問(wèn) t.p->a;//指針用->訪問(wèn)


          }聯(lián)合的使用規(guī)則幾乎和結(jié)構(gòu)體strtct的規(guī)則用法一樣,只不過(guò)是內(nèi)部表示的不同。
          補(bǔ)充:還有一個(gè)是無(wú)名聯(lián)合體,它是和無(wú)名結(jié)構(gòu)體的工作原理是相同的
          #include<stdio.h>//簡(jiǎn)單的例子#include<string.h>
          typedef union _node{ int a; double b; char c[20];
          }NODE;
          int main(void) {
          NODE a;//這里只定義一個(gè)變量
          a.a = 666; printf("%d\n", a.a);
          a.b = 9.99; printf("%f\n", a.b);
          strcpy(a.c, "hello world!"); printf("%s\n", a.c);
          //我們看到,三個(gè)都被完整的輸出了,因?yàn)樵谕粫r(shí)刻,只有一個(gè)成員是有效的
          }
          輸出:6669.990000hellow world!

          共用體的作用:

          1、節(jié)省內(nèi)存,有兩個(gè)很長(zhǎng)的數(shù)據(jù)結(jié)構(gòu),不會(huì)同時(shí)使用,比如一個(gè)表示老師,一個(gè)表示學(xué)生,如果要統(tǒng)計(jì)教師和學(xué)生的情況用結(jié)構(gòu)體的話就有點(diǎn)浪費(fèi)了!用結(jié)構(gòu)體的話,只占用最長(zhǎng)的那個(gè)數(shù)據(jù)結(jié)構(gòu)所占用的空間,就足夠了!

          2、實(shí)現(xiàn)不同類型數(shù)據(jù)之間的類型轉(zhuǎn)換,遇到各種類型的數(shù)據(jù)共用存儲(chǔ)空間,很方便的實(shí)現(xiàn)了不同數(shù)據(jù)類型之間的轉(zhuǎn)換,不需要顯示的強(qiáng)制類型轉(zhuǎn)換。

          其他:

          1、確定CPU的模式:大端、小端模式確定

          大小端不同,則存儲(chǔ)的方式也存在差別,比如int需要4個(gè)字節(jié),而char只需要1個(gè)字節(jié),根據(jù)1個(gè)字節(jié)所在的具體位置即可判定CPU的模式

          2、寄存器的定義,實(shí)現(xiàn)整體的訪問(wèn)和單項(xiàng)的訪問(wèn)

          //共用體綜合例子:根據(jù)輸入的數(shù)據(jù)類型輸出需要的相應(yīng)的數(shù)據(jù)#include<stdio.h>#include<string.h>//數(shù)據(jù)類型輸出   5*4  m n     n的第幾個(gè)x 
          union node { int a; double b; char c[30];
          }add[10000];
          char p[10000][30]; //保存的字符串?dāng)?shù)組
          int main(void) { int n, m; scanf("%d %d", &n, &m); int x; double y; char t[50]; int i, j;
          for (i = 0; i < n; i++) {//輸入 scanf("%s", &p[i]);//作為字符串?dāng)?shù)組,需要取地址
          if (strcmp("INT", p[i]) == 0) {//整形 scanf("%d", &x); add[i].a = x; } else if(strcmp("DOUBLE",p[i])==0){//浮點(diǎn) scanf("%lf", &y); add[i].b = y; } else if (strcmp("STRCING", p[i]) == 0) {//字符串 scanf("%s", t); strcpy(add[i].c, t); }
          }
          for (i = 0; i < m; i++) {//輸出 scanf("%d", &j);
          if (strcmp("INT", p[j]) == 0) { printf("%d\n", add[j].a); } else if (strcmp("DOUBLE", p[j]) == 0) { printf("%f\n", add[j].b); }else if(strcmp("STRING",p[j])==0) { printf("%s\n", add[j].c);
          }
          }
          return 0;
          }
          //輸入:/*5 4INT 456DOUBLE 123.56DOUBLE 0.476STRING welcomeToCSTRING LemonTree0124*/
          //輸出:/*456123.560.48LemonTree
          */

          希望對(duì)你有幫助!

          版權(quán)聲明:本文來(lái)源網(wǎng)絡(luò),免費(fèi)傳達(dá)知識(shí),版權(quán)歸原作者所有。如涉及作品版權(quán)問(wèn)題,請(qǐng)聯(lián)系我進(jìn)行刪除。

          ????????????????  END  ???????????????

               
               

          關(guān)注我的微信公眾號(hào),回復(fù)“加群”按規(guī)則加入技術(shù)交流群。

               
               

          點(diǎn)擊“閱讀原文”查看更多分享,歡迎點(diǎn)分享、收藏、點(diǎn)贊、在看。

          瀏覽 1857
          點(diǎn)贊
          評(píng)論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報(bào)
          評(píng)論
          圖片
          表情
          推薦
          點(diǎn)贊
          評(píng)論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報(bào)
          <kbd id="afajh"><form id="afajh"></form></kbd>
          <strong id="afajh"><dl id="afajh"></dl></strong>
            <del id="afajh"><form id="afajh"></form></del>
                1. <th id="afajh"><progress id="afajh"></progress></th>
                  <b id="afajh"><abbr id="afajh"></abbr></b>
                  <th id="afajh"><progress id="afajh"></progress></th>
                  操操网伊人网 | 免费 无码 国产真人视频 | 日本婷婷 | 国产天天操女人 | 丁香五月国内自拍 |