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

          C語言中匿名的最高境界

          共 3251字,需瀏覽 7分鐘

           ·

          2022-11-22 21:30

          C語言中有沒有見過(int [2]){19,20}或者int (*pt2)[4]的使用方法,字面上可能不好理解,這是C99之后才新增的知識點,名為復(fù)合型表述Compound Literals,一旦熟悉使用,便會體會到它簡潔而強大的表達(dá)。

          什么是”復(fù)合型表述“?

          假設(shè)給帶int類型的形參函數(shù)傳遞一個值,可以傳遞int類型的變量,也可以傳遞int類型常量,但是對于帶數(shù)組形參的函數(shù)則不一樣,可以傳遞數(shù)組,但是不支持傳遞數(shù)組常量,由此C99新增了“復(fù)合形表述”的用法,“表述(Literals)”是指除符號常量外的常量。

          例如10是一種int的類型的表述,10.24是一種double類型的表述,“l(fā)ixiaoyao”是一種字符串類型的表述等——這些都是關(guān)于單個類型常量值的表述。自然而然的,對于數(shù)組或者結(jié)構(gòu)體這種內(nèi)部存在多個成員的數(shù)據(jù)類型,其關(guān)于常量的表述就叫做復(fù)合型表述。

          關(guān)于數(shù)組的復(fù)合型表述

          數(shù)組的復(fù)合型表述和數(shù)組初始化列表差不多,前面使用括號括起來的類型名,例如下面是一個普通的數(shù)組聲明。

          int age[2]=[19,20];

          下面創(chuàng)建了一個和age數(shù)組相同的匿名數(shù)組,也有兩個int類型值。

          (int [2]){19,20}; //復(fù)合型表述

          注意去掉申明中的數(shù)組名,留下的int[2]就是復(fù)合型表述的類型名。

          初始化有數(shù)組名的數(shù)組可以省略數(shù)組的大小,復(fù)合型表述也可以省略大小,編譯器會自動計算數(shù)組當(dāng)前的元素個數(shù):

          (int []){19,20,21,22,23}//內(nèi)含5個元素的復(fù)合型表述

          因為復(fù)合型表述是匿名的,所以不能先創(chuàng)建然后再使用它,必須在創(chuàng)建的同時使用它,如下:

          int x;
          // 正確
          x = 100;

          int arr[1];
          // 錯誤
          arr = {0};

          一般需要這樣定義使用:

          int *pt1;
          pt1=(int[2]){19,20};

          注意,該復(fù)合型表述的字面常量與上面創(chuàng)建age數(shù)組的表述量完全相同,復(fù)合型表述的類型名也代表著首元素的地址,所以可以把它賦給指向int的指針。

          作為實際參數(shù)

          復(fù)合型表述作為實際參數(shù)傳遞給帶有匹配形式參數(shù)的函數(shù)。

          #include <stdio.h>
          int sum(const int age[],int n);

          int main () {
            int total;
            total =sum((int[]){4,4,4,5,5,5},6);
           return 0;
          }

          int sum(const int age[],int n){
           int i=0;
           for(i=0;i<n;i++){
            printf("age is %d\n",age[i]);
           }
          }

          輸出結(jié)果如下:

          應(yīng)用于二維數(shù)組或者多維數(shù)組

          這種用法還可以應(yīng)用于二維或者多維數(shù)組,例如下面演示了如何創(chuàng)建二維int數(shù)組并存儲其地址。

          int (*pt2)[4];
          //申明一個指向二維數(shù)組的指針,該數(shù)組內(nèi)有2個數(shù)組元素
          //每個元素是內(nèi)含4個int類型值的數(shù)組
          pt2 = (int [2][4]) {{1,2,3,4,},{5,6,7,8,}};

          對于結(jié)構(gòu)體

          假設(shè)如下所示聲明了struct foo和structure:

          struct foo {
            int a; 
            char b[2];
          } structure;

          這是使用復(fù)合型表述構(gòu)造struct foo的示例:

          structure = ((struct foo) {x + y, 'a', 0});

          這等效于以下代碼:

          {
            struct foo temp = {x + y, 'a', 0};
            structure = temp;
          }

          也可以構(gòu)造一個數(shù)組,如下所述,如果復(fù)合型表述的所有元素都是由簡單的常量表達(dá)式組成,則可以將復(fù)合型表述強制轉(zhuǎn)換為指向其第一個元素的指針,并在此類初始化程序中使用, 如下所示:

          char **foo = (char *[]) { "x""y""z" };

          標(biāo)量類型和聯(lián)合類型的復(fù)合型表述也被允許,在下面的示例中,變量i初始化為值2,該值是由復(fù)合型表述創(chuàng)建的未命名對象遞增的結(jié)果。

          int i = ++(int){1};

          作為GNU擴展,GCC允許通過復(fù)合型表述初始化具有靜態(tài)存儲持續(xù)時間的對象,如果復(fù)合型表述和對象的類型匹配,則如同僅使用括號括起來的列表初始化對象一樣處理該對象,復(fù)合型表述的元素必須是常量。如果要初始化的對象具有未知大小的數(shù)組類型,則該大小由復(fù)合型表述的大小確定。

          static struct foo x = (struct foo) {1, 'a''b'};
          static int y[] = (int []) {1, 2, 3};
          static int z[] = (int [3]) {1};

          等效于以下內(nèi)容:

          static struct foo x = {1, 'a''b'};
          static int y[] = {1, 2, 3};
          static int z[] = {1, 0, 0};

          C/C++中的區(qū)別

          復(fù)合型表述看起來像是用括號括起來的聚合初始化程序列表的強制轉(zhuǎn)換,它的值是強制類型轉(zhuǎn)換中指定類型的對象,其中包含初始化程序中指定的元素。

          與強制轉(zhuǎn)換的結(jié)果不同,復(fù)合型表述是左值,但是 C++ 中目前還沒有這種無名左值,作為擴展,GCC在C90模式和C++中也支持復(fù)合型表述,但C++語義有所不同。

          在C中,復(fù)合型表述表示具有靜態(tài)或自動存儲持續(xù)時間的未命名對象;在C++中,復(fù)合型表述表示一個臨時對象,該對象僅在其完整表達(dá)式結(jié)束之前一直存在。

          所以,定義良好的C代碼(采用復(fù)合型表述的子對象的地址)可以在C++中未定義,因此g++編譯器不能將臨時數(shù)組轉(zhuǎn)換為指針。

          例如,如果上面的數(shù)組復(fù)合型表述示例出現(xiàn)在函數(shù)內(nèi)部,則C++中對foo的任何后續(xù)使用都將具有未定義的行為,因為數(shù)組的生存期在聲明foo之后結(jié)束。

          作為一種優(yōu)化,g++編譯器有時會給數(shù)組復(fù)合型表述提供更長的生存期:當(dāng)數(shù)組出現(xiàn)在函數(shù)外部或具有const限定類型時。如果foo及其初始化程序的元素類型為char * const而不是char *,或者foo為全局變量,則該數(shù)組將具有靜態(tài)存儲持續(xù)時間。

          參考:https://gcc.gnu.org/onlinedocs/gcc/Compound-Literals.html

          END

          作者:李肖遙
          來源:技術(shù)讓夢想更偉大

          版權(quán)歸原作者所有,如有侵權(quán),請聯(lián)系刪除。

          瀏覽 46
          點贊
          評論
          收藏
          分享

          手機掃一掃分享

          分享
          舉報
          評論
          圖片
          表情
          推薦
          點贊
          評論
          收藏
          分享

          手機掃一掃分享

          分享
          舉報
          <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>
                  操逼操123 | 激情肏逼网 | 三年无码一区二区三区 | 国产亲子乱淫一级a片 | 久久色免费视频 |