国产chinesehdxxxx野外,国产av无码专区亚洲av琪琪,播放男人添女人下边视频,成人国产精品一区二区免费看,chinese丰满人妻videos

C語(yǔ)言 其它邊角知識(shí)

2018-09-29 18:43 更新

非局部跳轉(zhuǎn)

在 C 中,goto 語(yǔ)句是不能跨越函數(shù)的,而執(zhí)行這類(lèi)跳轉(zhuǎn)功能的是 setjmp 和 longjmp 宏。這兩個(gè)宏對(duì)于處理發(fā)生在深層嵌套函數(shù)調(diào)用中的出錯(cuò)情況是非常有用的。
此即為:非局部跳轉(zhuǎn)。非局部指的是,這不是由普通 C 語(yǔ)言 goto 語(yǔ)句在一個(gè)函數(shù)內(nèi)實(shí)施的跳轉(zhuǎn),而是在棧上跳過(guò)若干調(diào)用幀,返回到當(dāng)前函數(shù)調(diào)用路徑的某個(gè)函數(shù)中。

#include <setjmp.h>
int  setjmp (jmp_buf env) ;  /*設(shè)置調(diào)轉(zhuǎn)點(diǎn)*/
void longjmp (jmp_buf env,  int val) ;  /*跳轉(zhuǎn)*/

setjmp 參數(shù) env 的類(lèi)型是一個(gè)特殊類(lèi)型 jmp_buf。這一數(shù)據(jù)類(lèi)型是某種形式的數(shù)組,其中存放 在調(diào)用 longjmp 時(shí)能用來(lái)恢復(fù)棧狀態(tài)的所有信息。因?yàn)樾柙诹硪粋€(gè)函數(shù)中引用 env 變量,所以應(yīng)該將 env 變量定義為全局變量。
longjmp 參數(shù) val,它將成為從 setjmp 處返回的值。

#include <stdio.h>  
#include <setjmp.h>  

static jmp_buf buf;  

void second(void)   
{  
    printf("second\n");  
    longjmp(buf,1);              
    // 跳回setjmp的調(diào)用處使得setjmp返回值為1  
}  

void first(void)   
{  
    second();  
    printf("first\n");            
    // 不可能執(zhí)行到此行  
}  

int main()   
{     
    if (!setjmp(buf))   
    {  
        // 進(jìn)入此行前,setjmp返回0  
        first();  
    }   
    else   
    {     
        // 當(dāng)longjmp跳轉(zhuǎn)回,setjmp返回1,因此進(jìn)入此行  
        printf("main\n");  
    }  

    return 0;  
}

直接調(diào)用 setjmp 時(shí),返回值為 0,這一般用于初始化(設(shè)置跳轉(zhuǎn)點(diǎn)時(shí))。以后再調(diào)用 longjmp 宏時(shí)用 env 變量進(jìn)行跳轉(zhuǎn)。程序會(huì)自動(dòng)跳轉(zhuǎn)到 setjmp 宏的返回語(yǔ)句處,此時(shí) setjmp 的返回值為非 0,由 longjmp 的第二個(gè)參數(shù)指定。
一般地,宏 setjmp 和 longjmp 是成對(duì)使用的,這樣程序流程可以從一個(gè)深層嵌套的函數(shù)中返回

變長(zhǎng)參數(shù)列表

\ 頭文件定義了一些宏,當(dāng)函數(shù)參數(shù)未知時(shí)去獲取函數(shù)的參數(shù)變量:typedef va_list

宏:
va_start()
va_arg()
va_end()

va_list 類(lèi)型通過(guò) stdarg 宏定義來(lái)訪問(wèn)一個(gè)函數(shù)的參數(shù)表,參數(shù)列表的末尾會(huì)用省略號(hào)省略
( va_list 用來(lái)保存 va_start , va_end 所需信息的一種類(lèi)型。為了訪問(wèn)變長(zhǎng)參數(shù)列表中的參數(shù),必須聲明 va_list 類(lèi)型的一個(gè)對(duì)象 )

我們通過(guò)初始化( va_start )類(lèi)型為 va_list 的參數(shù)表指針,并通過(guò) va_arg 來(lái)獲取下一個(gè)參數(shù)。

//求任意個(gè)整數(shù)的最大值
#include <stdio.h>  
#include <stdarg.h>  

int maxint(int n, ...)         /* 參數(shù)數(shù)量由非變長(zhǎng)參數(shù)n直接指定 */  
{  
    va_list ap;  
    int     i, arg, max;  

    va_start(ap, n);           /* ap為參數(shù)指針,首先將其初始化為最后一個(gè)具名參數(shù), 以便va_arg獲取下一個(gè)省略號(hào)內(nèi)參數(shù) */  
    for (i = 0; i < n; i++) {  
        arg = va_arg(ap, int); /* 類(lèi)型固定為int, 按照給定類(lèi)型返回下一個(gè)參數(shù) */  
        if (i == 0)              
            max = arg;             
        else {  
            if (arg > max)  
                max = arg;  
        }  
    }  
    va_end(ap);  
    return max;  
}  

void main()  
{  
    printf("max = %d\n", maxint(5, 2, 6, 8, 11, 7));     
}  

可變長(zhǎng)數(shù)組

歷史上,C語(yǔ)言只支持在編譯時(shí)就能確定大小的數(shù)組。程序員需要變長(zhǎng)數(shù)組時(shí),不得不用malloc或calloc這樣的函數(shù)為這些數(shù)組分配存儲(chǔ)空間,且涉及到多維數(shù)組時(shí),不得不顯示地編碼,用行優(yōu)先索引將多維數(shù)組映射到一維的數(shù)組。
ISO C99引入了一種能力,允許數(shù)組的維度是表達(dá)式,在數(shù)組被分配的時(shí)候才計(jì)算出來(lái)。

#include <stdio.h>  

int  main(void)  
{  
    int n, i ;  

    scanf("%d", &n) ;   

    int array[n] ;   
    for (; i<n; i++)  
    {  
        array[i] = i ;  
    }  

    for (i=0; i<n; i++)  
    {  
        printf("%d,", array[i]) ;  
    }  

    return 0;  
} 

注意:
如果你需要有著變長(zhǎng)大小的臨時(shí)存儲(chǔ),并且其生命周期在變量?jī)?nèi)部時(shí),可考慮VLA(Variable Length Array,變長(zhǎng)數(shù)組)。但這有個(gè)限制:每個(gè)函數(shù)的空間不能超過(guò)數(shù)百字節(jié)。因?yàn)?C99 指出邊長(zhǎng)數(shù)組能自動(dòng)存儲(chǔ),它們像其他自動(dòng)變量一樣受限于同一作用域。即便標(biāo)準(zhǔn)未明確規(guī)定,VLA 的實(shí)現(xiàn)都是把內(nèi)存數(shù)據(jù)放到棧中。VLA 的最大長(zhǎng)度為 SIZE_MAX 字節(jié)??紤]到目標(biāo)平臺(tái)的棧大小,我們必須更加謹(jǐn)慎小心,以保證程序不會(huì)面臨棧溢出、下個(gè)內(nèi)存段的數(shù)據(jù)損壞的尷尬局面。

switch語(yǔ)句中的case

case支持范圍取值(gcc擴(kuò)展特性)

#include <stdio.h>  

int  main(void)  
{  
    int i=0;   
    scanf("%d", &i) ;  

    switch(i)  
    {  
     case 1 ... 9:  putchar("0123456789"[i]);     
     case 'A' ... 'Z':    //do something  
     }   

     return 0;  
}  

case 關(guān)鍵詞可以放在if-else或者是循環(huán)當(dāng)中

switch (a)  
{  
    case 1:    ;  
      // ...  
      if (b==2)  
      {  
        case 2:;  
        // ...  
      }  
      else case 3:  
      {  
        // ...  
        for (b=0;b<10;b++)  
        {  
          case 5:   ;  
          // ...  
        }  
      }  
      break;  

    case 4:  
} 

指定初始化(C99)

在C99之前,你只能按順序初始化一個(gè)結(jié)構(gòu)體。在C99中你可以這樣做:

struct Foo {
    int x;
    int y;
    int z;
};
Foo foo = {.z = 3, .x = 5};

這段代碼首先初始化了foo.z,然后初始化了foo.x. foo.y 沒(méi)有被初始化,所以被置為0。
這一語(yǔ)法同樣可以被用在數(shù)組中。以下三行代碼是等價(jià)的:

int a[5] = {[1] = 2, [4] = 5};
int a[]   = {[1] = 2, [4] = 5};
int a[5] = {0, 2, 0, 0, 5};

受限指針(C99)

關(guān)鍵字 restrict 僅對(duì)指針有用,修飾指針,表明要修改這個(gè)指針?biāo)赶虻臄?shù)據(jù)區(qū)的內(nèi)容,僅能通過(guò)該指針來(lái)實(shí)現(xiàn),此關(guān)鍵字的作用是使編譯器優(yōu)化代碼,生成更高效的匯編代碼。

int foo (int* x, int* y)  
{  
    *x = 0;  
    *y = 1;  
    return *x;  
} 

很顯然函數(shù)foo()的返回值是0,除非參數(shù)x和y的值相同。可以想象,99%的情況下該函數(shù)都會(huì)返回0而不是1。然而編譯起必須保證生成100%正確的代碼,因此,編譯器不能將原有代碼替換成下面的更優(yōu)版本

int f (int* x, int* y)  
{  
    *x = 0;  
    *y = 1;  
    return 0;  
} 

現(xiàn)在我們有了 restrict 這個(gè)關(guān)鍵字,就可以利用它來(lái)幫助編譯器安全的進(jìn)行代碼優(yōu)化了,由于指針 x 是修改 x的唯一途徑,編譯起可以確認(rèn) “ y=1; ”這行代碼不會(huì)修改 * x的內(nèi)容,因此可以安全的優(yōu)化。

int f (int *restrict x, int *restrict y)  
{  
    *x = 0;  
    *y = 1;  
    return 0;  
}  

很多C的庫(kù)函數(shù)中用restrict關(guān)鍵字:
void memcpy( void restrict dest ,const void restrict src,sizi_t n)
這是一個(gè)很有用的內(nèi)存復(fù)制函數(shù),由于兩個(gè)參數(shù)都加了 restrict 限定,所以?xún)蓧K區(qū)域不能重疊,即 dest 指針?biāo)傅膮^(qū)域,不能讓別的指針來(lái)修改,即 src 的指針不能修改. 相對(duì)應(yīng)的別一個(gè)函數(shù) memmove(void dest,const void * src,size_t)則可以重疊。

靜態(tài)數(shù)組索引(C99)

void f(int a[static 10]) {
    /* ... */
}

你向編譯器保證,你傳遞給 f 的指針指向一個(gè)具有至少10個(gè) int 類(lèi)型元素的數(shù)組的首個(gè)元素。我猜這也是為了優(yōu)化;例如,編譯器將會(huì)假定 a 非空。編譯器還會(huì)在你嘗試要將一個(gè)可以被靜態(tài)確定為 null 的指針傳入或是一個(gè)數(shù)組太小的時(shí)候發(fā)出警告。

void f(int a[const]) {
    /* ... */
}

你不能修改指針 a.,這和說(shuō)明符 int * const a.作用是一樣的。然而,當(dāng)你結(jié)合上一段中提到的 static 使用,比如在int a[static const 10] 中,你可以獲得一些使用指針風(fēng)格無(wú)法得到的東西。

多字符常量

int x = 'ABCD' ;  

這會(huì)把 x 的值設(shè)置為 0×41424344(或者0×44434241,取決于大小端)我們一般的小端機(jī)上,低位存在低字節(jié)處,DCBA 依次從低字節(jié)到高字節(jié)排列。
這只是一種看起來(lái)比較炫酷的寫(xiě)法,一般沒(méi)什么用。

以上內(nèi)容是否對(duì)您有幫助:
在線筆記
App下載
App下載

掃描二維碼

下載編程獅App

公眾號(hào)
微信公眾號(hào)

編程獅公眾號(hào)