日韩黑丝制服一区视频播放|日韩欧美人妻丝袜视频在线观看|九九影院一级蜜桃|亚洲中文在线导航|青草草视频在线观看|婷婷五月色伊人网站|日本一区二区在线|国产AV一二三四区毛片|正在播放久草视频|亚洲色图精品一区

分享

關(guān)于volatile和restrict關(guān)鍵字

 e3399 2012-05-24
關(guān)于volatile和restrict關(guān)鍵字
2007-10-15 18:55
volatile 可能我們用的都比較多也比較常見吧,主要就是告訴編譯器,每次在使用volatile指定的變量時總是重新去獲取他的值,更簡單的理解我是這樣的,
為了計算某個內(nèi)容地址所存的內(nèi)容會把他放入CPU寄存器,為了優(yōu)化,下一次就直接從寄存器里取值了
volatile就是為了告訴編譯器,不管什么情況你都要去內(nèi)存里重新獲取他的內(nèi)容!!嘻嘻*^_^*

restrict就比較少見了。
restrict說明這個變量沒有別的指針可以修改,讓編譯器生成只讀內(nèi)存一次的代碼。


'Restrict' Pointers
One of the new features in the recently approved C standard C99, is the restrict pointer qualifier. This qualifier can be applied to a data pointer to indicate that, during the scope of that pointer declaration, all data accessed through it will be accessed only through that pointer but not through any other pointer. The 'restrict' keyword thus enables the compiler to perform certain optimizations based on the premise that a given object cannot be changed through another pointer. Now you're probably asking yourself, "doesn't const already guarantee that?" No, it doesn't. The qualifier const ensures that a variable cannot be changed through a particular pointer. However, it's still possible to change the variable through a different pointer. For example:

 

void f (const int* pci, int *pi;); // is *pci immutable?
{
(*pi)+=1; // not necessarily: n is incremented by 1
*pi = (*pci) + 2; // n is incremented by 2
}
int n;
f( &n, &n);

In this example, both pci and pi point to the same variable, n. You can't change n's value through pci but you can change it using pi. Therefore, the compiler isn't allowed to optimize memory access for *pci by preloading n's value. In this example, the compiler indeed shouldn't preload n because its value changes three times during the execution of f(). However, there are situations in which a variable is accessed only through a single pointer. For example:

 

FILE *fopen(const char * filename, const char * mode);

The name of the file and its open mode are accessed through unique pointers in fopen(). Therefore, it's possible to preload the values to which the pointers are bound. Indeed, the C99 standard revised the prototype of the function fopen() to the following:

 
/* new declaration of fopen() in <stdio.h> */
FILE *fopen(const char * restrict filename,
const char * restrict mode);

Similar changes were applied to the entire standard C library: printf(), strcpy() and many other functions now take restrict pointers:

 
int printf(const char * restrict format, ...);
char *strcpy(char * restrict s1, const char * restrict s2);

C++ doesn't support restrict yet. However, since many C++ compilers are also C compilers, it's likely that this feature will be added to most C++ compilers too.



c99中新增加了一個類型定義,就是restrict。
restrict 的定義是It can be applied only to pointers, and it indicates that a pointer is the sole initial means of accessing a data object.
我不知道確切應(yīng)該怎么翻譯,大意是restrict只對指針有用,它聲明一個指針是唯一初始化訪問一個數(shù)據(jù)對象。
比如,按照書上的例子,
int ar[10];
int * restrict restar = (int *) malloc(10 * sizeof(int));int * par = ar;
for (n = 0; n < 10; n++)
{      par[n] += 5;    
restar[n]
+= 5;  
    ar[n]
*= 2;  
    par[n]
+= 3;     
restar[n]
+= 3;
}


restar指針是restrict類型,par指針就不是,因為par即沒有初始化也不是唯一訪問ar數(shù)組的變量。
那么,上面的程序,因為restar是唯一反問數(shù)據(jù)塊的指針,所以編譯器可以對它優(yōu)化為一條語句,
restar[n] += 8;    /* ok replacement */
而par就不可以,
par[n] += 8;     / * gives wrong answer */
One of the new features in the recently approved C standard C99, is the restrict pointer qualifier. This qualifier can be applied to a data pointer to indicate that, during the scope of that pointer declaration, all data accessed through it will be accessed only through that pointer but not through any other pointer. The 'restrict' keyword thus enables the compiler to perform certain optimizations based on the premise that a given object cannot be changed through another pointer. Now you're probably asking yourself, "doesn't const already guarantee that?" No, it doesn't. The qualifier const ensures that a variable cannot be changed through a particular pointer. However, it's still possible to change the variable through a different pointer. For example:

     
void f (const int* pci, int *pi;); // is *pci immutable?
   {
      (
*pi)+=1; // not necessarily: n is incremented by 1
      *pi = (*pci) + 2; // n is incremented by 2
    }

   
int n;
    f(
&n, &n);

In this example, both pci and pi point to the same variable, n. You can't change n's value through pci but you can change it using pi. Therefore, the compiler isn't allowed to optimize memory access for *pci by preloading n's value. In this example, the compiler indeed shouldn't preload n because its value changes three times during the execution of f(). However, there are situations in which a variable is accessed only through a single pointer. For example:

FILE *fopen(const char * filename, const char * mode);

 

The name of the file and its open mode are accessed through unique pointers in fopen(). Therefore, it's possible to preload the values to which the pointers are bound. Indeed, the C99 standard revised the prototype of the function fopen() to the following:

     /* new declaration of fopen() in <stdio.h> */    
FILE *fopen(const char * restrict filename,
                         
const char * restrict mode);

Similar changes were applied to the entire standard C library: printf(), strcpy() and many other functions now take restrict pointers:
  

C++ doesn't support restrict yet. However, since many C++ compilers are also C compilers, it's likely that this feature will be added to most C++ compilers too.

  
所以,在沒有restrict的時候,編譯器需要考慮上面的出錯情況,而無法優(yōu)化程序。

restrict也可以用在函數(shù)的指針參數(shù)前面,它表示在函數(shù)里沒有其他標(biāo)識符會修改指針?biāo)傅臄?shù)據(jù)塊,編譯器可以優(yōu)化函數(shù)。

在C99中新增了類型修飾符(qualifier) restrict 在網(wǎng)上找來找去,看到介紹它的不多,就把看到的一些介紹做個總結(jié)。
傳說中下面是是書中的原話,到底是什么書卻沒人說:
========================8<====================================
restrict這種修飾符只適用于指針.
由restrict修飾的指針是最初唯一對指針?biāo)赶虻膶ο筮M(jìn)行存取的辦法,
僅當(dāng)?shù)诙€指針基于第一個時,才能對對象進(jìn)行存取.
因此,對對象的存取都限定于基于有restrict修飾的指針表達(dá)式中.
由restrict修飾的指針主要被用做函數(shù)指針,或者指向由malloc()分配的內(nèi)存變量.
restrict數(shù)據(jù)類型不改變程序的語義.
=======================8<=======================================
感覺說的有的亂,可能是我的理解能力不夠吧。然后在CSDN看到了這個:
========================8<====================================

restrict是C99版新增加的關(guān)鍵字!   如下:

      C99    中新增加了    restrict    修飾的指針: 由    restrict    修飾的指針是最初唯一對指針?biāo)赶虻膶ο筮M(jìn)行存取的方法,僅當(dāng)?shù)诙€指針基于第一個時,才能對對象進(jìn)行存取。對對象的存取都限定于基于由    restrict    修飾的指針表達(dá)式中。

      由    restrict    修飾的指針主要用于函數(shù)形參,或指向由    malloc()   分配的內(nèi)存空間。restrict   數(shù)據(jù)類型不改變程序的語義。   編譯器能通過作出    restrict   修飾的指針是存取對象的唯一方法的假設(shè),更好地優(yōu)化某些類型的例程。

      [典型例子]    memcpy()    在    C99    中,restrict    可明確用于    memcpy()    的原型,而在    C89    中必須進(jìn)行解釋。    void    *memcpy (void    *restrict    str1,    const    void    *restrict    str2,    size_t    size);    /*   通過使用    restrict    修飾    str1    和    str2    來保證它們指向不重疊的對象    */   

=======================8<=======================================
很多人說這個關(guān)鍵字主要是用來加強編譯器優(yōu)化的,理由也很簡單:“由restrict修飾的指針是最初唯一對指針?biāo)赶虻膶ο筮M(jìn)行存取的辦法,僅當(dāng)?shù)诙€指針基于第一個時,才能對對象進(jìn)行存取.”這樣下面的代碼就可以被很好的優(yōu)化,

void fcpy(float *restrict a, float *restrict b,
      
float *restrict aa, float *restrict bb, int n)
{
int i;
for(i = 0; i < n; i++) ...{
      aa[i]
=a[i];
      bb[i]
=b[i];
}

}

這意味著這些拷貝循環(huán)能夠“并行”(in parallel),由于 例如 aa != b
但還是喜歡下面的例子,從它可以看出restrict不僅僅可以被用來加強編譯器的優(yōu)化,還是解決我們代碼中存在的隱患。
=====================8<================================
'Restrict' Pointers

One of the new features in the recently approved C standard C99, is the restrict pointer qualifier. This qualifier can be applied to a data pointer to indicate that, during the scope of that pointer declaration, all data accessed through it will be accessed only through that pointer but not through any other pointer. The 'restrict' keyword thus enables the compiler to perform certain optimizations based on the premise that a given object cannot be changed through another pointer. Now you're probably asking yourself, "doesn't const already guarantee that?" No, it doesn't. The qualifier const ensures that a variable cannot be changed through a particular pointer. However, it's still possible to change the variable through a different pointer. For example:
<!--[if !supportLineBreakNewLine]-->
<!--[endif]-->

  void f (const int* pci, int *pi;); // is *pci immutable?
   {
     (*pi)+=1; // not necessarily: n is incremented by 1
      *pi = (*pci) + 2; // n is incremented by 2
   }
   int n;
   f( &n, &n);//
增加restrict關(guān)鍵字是因為這里會出問題
,
//
如果對兩個參數(shù)都使用了restrict關(guān)鍵字,那么這里編譯時會報錯,因為一

//
個地址可以通過兩個指針訪問了
<!--[if !supportLineBreakNewLine]-->

<!--[endif]-->

In this example, both pci and pi point to the same variable, n. You can't change n's value through pci but you can change it using pi. Therefore, the compiler isn't allowed to optimize memory access for *pci by preloading n's value. In this example, the compiler indeed shouldn't preload n because its value changes three times during the execution of f(). However, there are situations in which a variable is accessed only through a single pointer. For example:

   FILE *fopen(const char * filename, const char * mode);
<!--[if !supportLineBreakNewLine]-->
<!--[endif]-->

The name of the file and its open mode are accessed through unique pointers in fopen(). Therefore, it's possible to preload the values to which the pointers are bound. Indeed, the C99 standard revised the prototype of the function fopen() to the following:

/* new declaration of fopen() in <stdio.h>; */
   FILE *fopen(const char * restrict filename,
                         const char * restrict mode);

Similar changes were applied to the entire standard C library: printf(), strcpy() and many other functions now take restrict pointers:

int printf(const char * restrict format, ...);
   char *strcpy(char * restrict s1, const char * restrict s2);


C++ doesn't support restrict yet. However, since many C++ compilers are also C compilers, it's likely that this feature will be added to most C++ compilers too.

=====================8<================================
上面的例子簡單來說就是被const修飾的指針指向的內(nèi)容真的是不變的嗎?在某些情況下顯然不是,如第一段代碼

void f (const int* pci, int *pi ) // is *pci immutable?
   {
     (*pi)+=1; // not necessarily: n is incremented by 1
      *pi = (*pci) + 2; // n is incremented by 2
   }
   int n;
   f( &n, &n);

pci和pi指向的都是n,雖然pci被const修飾,但pci指向的內(nèi)容卻在函數(shù)中被改變了,當(dāng)用restrict修飾符之后 void f ( const int * restrict pci , int * restrict pi ),問題解決了:一旦我們再有如:f ( &n , &n ) 的調(diào)用,編譯器將給出錯誤提示,這是由于一個地址可以通過兩個指針來訪問。

restrict同樣可以用于數(shù)組的聲明:

If you specify type qualifiers such as void foo(int * restrict a);, the C compiler expresses it with array syntax void foo(int a[restrict]); which is essentially the same as declaring a restricted pointer.

寫 了這么多,總結(jié)一下,其實restrict同const或valiate一樣是一個修飾符而已,告訴編譯器被restrict修飾的指針?biāo)赶虻膶ο?,?能通過這個指針或基于這個指針的其他指針進(jìn)行操作,即限制訪問用restrict限制的指針指向的對象只能通過這個指針訪問,這對編譯器的優(yōu)化很有好處。

但要注意:restrictC99中新增的關(guān)鍵字,在C89C++中都不支持,在gcc中可以通過—std=c99來得到對它的支持。

    本站是提供個人知識管理的網(wǎng)絡(luò)存儲空間,所有內(nèi)容均由用戶發(fā)布,不代表本站觀點。請注意甄別內(nèi)容中的聯(lián)系方式、誘導(dǎo)購買等信息,謹(jǐn)防詐騙。如發(fā)現(xiàn)有害或侵權(quán)內(nèi)容,請點擊一鍵舉報。
    轉(zhuǎn)藏 分享 獻(xiàn)花(0

    0條評論

    發(fā)表

    請遵守用戶 評論公約

    類似文章 更多