2011-01-13 53 views
6

我一直在研究的GNU科學圖書館的源代碼,我總是看到以下類型聲明:C99常量傳遞按值

double cblas_ddot (const int N, const double * x, const int incx, const double * y, const int incy) 

C99,是否有任何(最優性充分)受益聲明通過值傳遞的參數(例如,上述示例中的Nincyconst?無論如何都有一份由他們製作的副本,因爲他們是按價值傳遞的,不是嗎?

Thx! Kornel

回答

11

調用者可能沒有任何好處,但對於被調用者。聲明函數參數const具有與聲明其他本地變量const相同的有益影響,只要您試圖修改此錯誤,您就會對自己(作爲函數的程序員)施加錯誤。

在不太聰明的實現中,如果函數被內聯,這樣的聲明可能也會對決定產生影響。但我想現在的編譯器會直接從函數的定義中推導出什麼樣的決定。

它當然可以看作是語言的限制,這個實現的規範是在其接口中表達的。

3

是的。 「const」選項通常用於聲明傳遞給該函數的內容不會被改變。編譯方面,沒有區別。它仍然值得傳遞。

3

正如其他人所說的那樣,函數是這樣聲明的,所以在函數的範圍內,該變量不會變化,這樣編譯器會警告你。至於爲什麼你可能想要這樣做,考慮一下傳遞一個指針允許你做什麼 - 也就是說,你可以取消引用已經傳遞的指針並編輯它所指向的數據的值。使用const是防止自己意外編輯調用者認爲未改變的東西的值的好方法。

例如,考慮一下:

#include <stdio.h> 

void add(int* result, const int* x, int* y) 
{ 
    *result = *x + *y; 
    (*y)++; /* <-- the caller won't expect this! */ 

} 

int main(int argc, char** argv) 
{ 
    int a = 7; 
    int b = 10; 
    int c = 0; 

    add(&c, &a, &b); 

    printf("%d + %d = %d\n", a, b, c); 
    return 0; 
} 

該吐出7+11=17。現在,這是一個簡單的,不嚴重的情況下,但各種東西可能是我們要依靠什麼重要的事發生......

如果你堅持常量對變量y,你應該得到:

constexample.c: In function ‘add’: constexample.c:7:5: error: increment of read-only location ‘*y’

編輯,進一步澄清:

一個很好的理由來聲明const類型的非指針變量是表示某物的大小,或者保持陣列的最大值的任何變量的變量。考慮:

int editstring(char* result, ..., const char* source, const size_t source_len); 

現在,你對自己說,但我永遠不會編輯source_len。那麼,讓我們說你的算法,無論出於何種原因。如果您的更改增加了source_len的值,則存在超出您分配的內存訪問內存的風險。設置const如果您嘗試修改該值,則會生成編譯器錯誤。

我應該在雙重下劃線中指出,const只是向編譯器說的一種方式:「我保證不編輯它」。它不保證內存只讀,但它是一種標記您的意圖的方式,以便捕獲錯誤。如果您不需要修改它,請將其聲明爲const。

而且由於您問了,兩個版本生成的程序集是相同的。

+2

在您的示例中,您不聲明參數'const',而是聲明參數指向的數據。對於指針而言,OP所要求的內容就像'int * const result'。另外,如果我沒有記錯,'* y ++'首先增加指針,然後解除引用。沒有什麼可以打擾來電者,不是嗎? –

+0

你是對的,我的錯誤應該是'(* y)++;'但是,我從來沒有說過,聲明我的參數const影響指針 - 實際上,我的例子中的*點*是它改變了源內存。儘管我已經在標準變量consts的有用性上添加了一個額外的部分。 – 2011-01-13 17:38:30