1. 程式人生 > >轉載 C語言中register型別的變數有什麼意義

轉載 C語言中register型別的變數有什麼意義

一般情況下,變數的值是儲存在記憶體中的,CPU 每次使用資料都要從記憶體中讀取。如果有一些變數使用非常頻繁,從記憶體中讀取就會消耗很多時間,例如 for 迴圈中的增量控制:

int i;
for(i=0; i<1000; i++){
    // Some Code
}

執行這段程式碼,CPU 為了獲得 i,會讀取 1000 次記憶體。

為了解決這個問題,可以將使用頻繁的變數放在CPU的通用暫存器中,這樣使用該變數時就不必訪問記憶體,直接從暫存器中讀取,大大提高程式的執行效率。

暫存器、快取、記憶體

為了加深對 register 變數的理解,這裡有必要講一下CPU暫存器。

按照與CPU的遠近來分,離CPU最近的是暫存器,然後是快取,最後是記憶體。

暫存器是最貼近CPU的,而且CPU只在暫存器中進行存取。寄存的意思是暫時存放資料,不用每次都從記憶體中取,它是一個臨時的存放資料的空間。

而暫存器的資料又來源於記憶體,於是 CPU <-- 暫存器 <-- 記憶體,這就是它們之間的資訊交換。

那麼為什麼還需要快取呢?因為如果頻繁地操作記憶體中同一地址上的資料會影響速度,於是就在暫存器和記憶體之間設定一個快取,把使用頻繁的資料暫時儲存到快取,如果暫存器需要讀取記憶體中同一地址上的資料,就不用大老遠地再去訪問記憶體,直接從快取中讀取即可。

快取的速度遠高於記憶體,價格也是如此。

注意:快取的容量是有限的,暫存器只能從快取中讀取到部分資料,對於使用不是很頻繁的資料,會繞過快取,直接到記憶體中讀取。所以不是每次都能從快取中得到資料,這就是快取的命中率,能夠從快取中讀取就命中,否則就沒命中。

關於快取的命中率又是一門學問,哪些資料保留在快取,哪些資料不保留,都有複雜的演算法。

注意:上面所說的CPU是指CPU核心,從市場上購買的CPU已是封裝好的套件,附帶了暫存器和快取,插到主機板上就可以用。

從經濟和速度的綜合考慮,快取又被分為一級快取、二級快取和三級快取,它們的存取速度和價格依次降低,容量依次增加。購買到的CPU一般會標出三級快取的容量。

register 變數

暫存器的數量是有限的,通常是把使用最頻繁的變數定義為 register 的。

來看一個計算 π 的近似值的例子,求解的一個近似公式如下:

為了提高精度,迴圈的次數越多越好,可以將迴圈的增量控制定義為暫存器變數,如下所示:

#include <stdio.h>
#include <conio.h>

int main()
{
    register int i = 0;  // 暫存器變數
    double sign = 1.0, res = 0, ad = 1.0;

    for(i=1; i<=100000000; i++)
    {
        res += ad;
        sign=-sign;
        ad=sign/(2*i+1);
    }

    res *= 4;
    printf("pi is %f", res);

    getch();
    return 0;
}

執行結果:
pi is 3.141593

關於暫存器變數有以下事項需要注意:
1) 為暫存器變數分配暫存器是動態完成的,因此,只有區域性變數和形式引數才能定義為暫存器變數。

2) 區域性靜態變數不能定義為暫存器變數,因為一個變數只能宣告為一種儲存類別。

3) 暫存器的長度一般和機器的字長一致,所以,只有較短的型別如int、char、short等才適合定義為暫存器變數,諸如double等較大的型別,不推薦將其定義為暫存器型別。

4) CPU的暫存器數目有限,因此,即使定義了暫存器變數,編譯器可能並不真正為其分配暫存器,而是將其當做普通的auto變數來對待,為其分配棧記憶體。當然,有些優秀的編譯器,能自動識別使用頻繁的變數,如迴圈控制變數等,在有可用的暫存器時,即使沒有使用 register 關鍵字,也自動為其分配暫存器,無須由程式設計師來指定。

相關推薦

轉載 C言中register型別變數什麼意義

一般情況下,變數的值是儲存在記憶體中的,CPU 每次使用資料都要從記憶體中讀取。如果有一些變數使用非常頻繁,從記憶體中讀取就會消耗很多時間,例如 for 迴圈中的增量控制: int i; for(i=0; i<1000; i++){ // Some C

C言中register型別變數什麼意義

一般情況下,變數的值是儲存在記憶體中的,CPU 每次使用資料都要從記憶體中讀取。如果有一些變數使用非常頻繁,從記憶體中讀取就會消耗很多時間,例如 for 迴圈中的增量控制: int i; for(i=0; i<1000; i++){ // Some Cod

c言中const 型別變數地址賦值給指標。

const在C語言中是表示道義上保證變數的值不會被修改,並不能實際阻止修改,通過指標可以修改常變數的值,但是會出現一些不可知的結果。幾種情況不同,我們一個一個來看。 1、直接賦值 const int a = 3; a = 5; // const.c:6:2: error: assignment of read

C言中static全域性變數與普通的全域性變數區別

下面是中興通訊2012校招筆試題的一道問答題: 1. static全域性變數與普通的全域性變數有什麼區別 ?   全域性變數(外部變數)的說明之前再冠以static 就構成了靜態的全域性變數。   全域性變數本身就是靜態儲存方式, 靜態全域性變數當然也是靜態儲存方式。 這兩者在儲存方式上

C言中 char 型別的取值範圍為什麼是-128~127

我們之前已經說過關於原碼、反碼和補碼的一些東西,如果你沒有看過,可以點這裡《 你知道原碼、反碼和補碼嗎,進來了解一下吧 》看一下 。 好了,可能你不會太想看,所以我們一起再來簡單的複習一下,如果我們現在有一個十進位制的整數 1 ,我們知道 1 個位元組等於 8 位,

C言中的static變數

歡迎交流 E-mail:ce123#126.com(#->@) QQ:350725201 嵌入式開發交流群: (1)280352802(已滿) (2)289195589 宣告:版權所有,歡迎轉載! 轉載請註明出處:http://blog.csdn.net/ce123

C言中‘,’運算子存在的意義

逗號運算子(‘,’)是C語言中優先順序最低的運算子,它用於連線兩個表示式(n-1個‘,’可以連線n個表示式)並從左至右執行表示式,最後一個表示式的值作為整個表示式的值。基本格式如下: 表示式1,表示式2,表示式3…,表示式n 舉個例子: #incl

C言中變數的儲存型別幾種?

在C語言中,對變數的儲存型別說明有以下四種:         auto          自動變數         register     暫存器變數         extern       外部變數         static         靜態變數       

轉載】在C言中,double、long、unsigned、int、char類型數據所占字節數

src 有關 指針變量 none nbsp ide iso isp cli 和機器字長及編譯器有關系: 所以,int,long int,short int的寬度都可能隨編譯器而異。但有幾條鐵定的原則(ANSI/ISO制訂的): 1 sizeof(short int)&

C言中%p,%u,%lu都什麽用處

整型 end sig 語言 進制 clas 長整型 sign ext %p表示輸出這個指針, %d表示後面的輸出類型為有符號的10進制整形, %u表示無符號10進制整型, %lu表示輸出無符號長整型整數 (long unsigned)C語言中%p,%u,%lu都有什麽用處

C言中%d,%p,%u,%lu等都什麽用處

abc 16進制 body def 進制數 什麽 整形 無符號 進制 %d   有符號10進制整數(%ld 長整型,%hd短整型 )%hu   無符號短整形(%u無符號整形,%lu無符號長整形)%i    有符號10進制整數 (%i 和%d 沒有區別,%i 是老式寫法,都是

C言中的struct和typedef struct<轉載>

對象 內部數據 編程 都是 內部 pre title HR 聲明 原文:http://www.nowamagic.net/librarys/veda/detail/1785 typedef為C語言的關鍵字,作用是為一種數據類型定義一個新名字。這裏的數據類型包括內部數據類

轉載C言中的static 詳細分析

          google了近三頁的關於C語言中static的內容,發現可用的資訊很少,要麼長篇大論不知所云要麼在關鍵之處幾個字略過,對於想挖掘底層原理的初學者來說參考性不是很大。所以,我這篇博文博採眾家之長,把網際網路上的資料整合歸類,並親手編寫程式驗證之。    

C言中int到float的強制型別轉換

最近在看一本名為的書。由於我所看過的計算機理論方面的書較少,加上自己大學期間一直也不用功,所以對於計算機的工作原理以及程式的工作方式我始終只知甚少,印象也十分模糊。 不過,應該說我碰到了一本好書。至少,通過昨晚對浮點數一章的閱讀(呃...我的確之前對浮點數從沒弄明白過),

C言中exit(0)與exit(1)什麼區別

今天天氣有點冷,當我在寫訊息佇列的程式的時候,遇到了結束程序的這個問題,突然腦海裡有點混亂,我是用_exit(),還是用exit(1),還是用exit(0)呢,然後自己度娘了一下,整理了一下稍微做

C言中,為什麼字串可以賦值給字元指標變數

1.以字串形式出現的,編譯器都會為該字串自動新增一個0作為結束符,如在程式碼中寫  "abc",那麼編譯器幫你儲存的是"abc\0" 2."abc"是常量嗎?答案是有時是,有時不是。 不是常量的情況:"abc"作為字元陣列初始值的時候就不是,如                  char str[] = "

C言中printf和scanf函式基本的引數型別和輸出形式

printf函式的引數型別和輸出形式 字元 引數型別 輸出形式 d,i int 十進位制數 o int 無符號八進位制數(不含前導0) x,X int 無符號十六進位制數(沒有前

C言中,int ,char 等幾種資料型別所佔用的空間

在32位處理器中,int a;  sizeof(a)=4;char a; sizeof(a)=1;float a; sizeof(a)=4;double a; sizeof(a)=8;long a; sizeof(a)=4;long int  a; sizeof(a)=4;s

c言中32為地址型別轉換為64位整數型別

uint64_t idt_operand = ((sizeof(idt) - 1) | ((uint64_t)(uint32_t)idt << 16)); idt是陣列名,也就是結構陣列型別的指標。static struct gate_desc idt[IDT

C言中被static修飾的函式或變數

被static修飾的函式可認為是“區域性函式”,只能被本原始碼檔案訪問。而沒有static關鍵字的函式可認為是全域性函式(可在函式前寫上extern,此關鍵字是預設的,所以可不寫),可跨檔案被訪問。st