我在這里有這個代碼:
#include <stdio.h>
int add(const int* x, const int* y);
int main()
{
int x = 4;
int y = 3;
printf("%d", add(&x, &y));
return 0;
}
int add(int* x, int* y)
{
return *x *y;
}
當我編譯它給我一個錯誤:沖突型別添加
我知道我必須將常量放入函式定義的引數中。
但是,如果我在代碼中添加一個 typedef,如下所示:
#include <stdio.h>
typedef int* int_ptr;
int add(const int_ptr x, const int_ptr y);
int main()
{
int x = 4;
int y = 3;
printf("%d", add(&x, &y));
return 0;
}
int add(int_ptr x, int_ptr y)
{
return *x *y;
}
它編譯并給了我輸出:7
為什么會發生這種情況?
uj5u.com熱心網友回復:
在 中const int* x,const int是說明符,*x是宣告符。(這種分離是由 C 的形式語法指定的,這也是為什么將宣告寫成int* x錯誤表示語法的原因。)這個宣告說*x是 a const int,意思x是指向 的指標const int。
在typedef int* int_ptr,typedef int是說明符,*int_ptr是宣告符。宣告說這*int_ptr是一個int, 并且typedef是一個特殊的說明符,它修改它以便int_ptr被宣告為一個型別,而不是一個物件(變數)。
在const int_ptr x,const int_ptr是說明符,x是宣告。所以這個宣告說這x是一個const int_ptr.
這里const是修改int_ptr;const int_ptr x說那x是一個const指向 an的指標int。在const int *x,const修改int,所以它說*x是一個指向 a 的指標const int,意思x是一個指向 a 的指標const int。
大多數情況下,當使用引數型別串列宣告函式時,引數在函式的每個宣告中都必須具有兼容的型別。但有一個例外:C 2018 6.7.6.3 15 說:
……(在確定型別兼容性和復合型別時,……使用限定型別宣告的每個引數都被視為具有其宣告型別的非限定版本。)
這就是說,在確定是否int add(const int_ptr x, const int_ptr y)與 兼容時int add(int_ptr x, int_ptr y),將const忽略限定符。那么引數型別是相同的,所以函式宣告是兼容的。
在int add(const int *x, const int *y),x并y沒有資格與const。他們指向const int,但他們自己不是const。也就是說,x可以更改的指標(不是const)。事實上,它指向的東西const并不構成它const。所以忽略函式引數中的限定符的規則在這里不適用;x和上沒有限定詞y。所以int add(const int *x, const int *y)并int add(int *x, int *y)沒有兼容的引數型別。
這條關于忽略引數型別中的限定符的規則的原因來自這樣一個事實,即限定符只影響物件,而不影響值。如果我們有一個物件x是const,它不應該被改變(通過型別)。但是,如果我們已經得到int值 3x并在運算式中使用它,那么說 3 is 就沒有意義了const。它只是在運算式中使用的一個值;沒有分配給它的記憶體,我們可以在其中存盤一個新值,該值將更改為 3 到 4。一旦從 a 檢索物件的值const int,它只是一個int。
類似地,如果我們有 a volatile int x,這volatile意味著編譯器x每次在運算式中使用它時都必須獲取 的值,因為這volatile意味著某些東西可能會x以編譯器不知道的方式改變記憶體。但是,一旦我們x從記憶中獲得了 的值,它就只是一個值。我們已經完成了“你必須從記憶體中獲取它”的部分,所以volatile沒有更多的影響。
由于函式引數總是按值傳遞,限定符與呼叫者無關。當一個函式與宣告void foo(const int x),該const具有的功能里面的含義:編譯器必須發出診斷,如果函式嘗試內部的任何修改x其const-qualified型別。但呼叫者并不關心:呼叫者只傳遞一個值。當該功能啟動時,它會創建一個本地x的一樣,這x是const,但對呼叫者沒有影響。所以void foo(int x)和void foo(const int x)是兼容的函式宣告。
轉載請註明出處,本文鏈接:https://www.uj5u.com/qianduan/382569.html
