3 回答

TA貢獻1828條經(jīng)驗 獲得超6個贊
您在帖子中所說的是絕對正確的。我想說的是,每位C開發(fā)人員在達到一定水平的C語言水平時都會得出完全相同的發(fā)現(xiàn)和得出完全相同的結(jié)論。
當您的應用程序區(qū)域的細節(jié)要求特定固定大小的數(shù)組(數(shù)組大小是編譯時常量)時,將此類數(shù)組傳遞給函數(shù)的唯一正確方法是使用指針數(shù)組參數(shù)
void foo(char (*p)[10]);
(在C ++語言中,這也可以通過引用來完成
void foo(char (&p)[10]);
)。
這將啟用語言級別的類型檢查,這將確保提供大小完全正確的數(shù)組作為參數(shù)。實際上,在許多情況下,人們甚至沒有意識到就暗中使用此技術(shù),而是將數(shù)組類型隱藏在typedef名稱后面
typedef int Vector3d[3];
void transform(Vector3d *vector);
/* equivalent to `void transform(int (*vector)[3])` */
...
Vector3d vec;
...
transform(&vec);
另外請注意,上述代碼對于Vector3dtype是數(shù)組還是a 是不變的struct。您可以Vector3d隨時將數(shù)組的定義從a 切換到a struct,然后再切換回來,而不必更改函數(shù)聲明。在這兩種情況下,函數(shù)都將“通過引用”接收聚合對象(對此有一些例外,但是在此討論的上下文中,這是正確的)。
但是,您不會看到這種顯式使用數(shù)組傳遞的方法被頻繁地使用,這僅僅是因為太多的人對相當復雜的語法感到困惑,并且根本不適應C語言的此類功能以正確使用它們。因此,在一般現(xiàn)實生活中,將數(shù)組作為指向其第一個元素的指針傳遞是一種更為流行的方法。它看起來只是“簡單”。
但實際上,使用指向第一個元素的指針進行數(shù)組傳遞是一種非常特殊的技術(shù),這是一個技巧,它具有非常特定的目的:其唯一的目的是促進傳遞大小不同(即運行時大小)的數(shù)組。如果您確實需要能夠處理運行時大小的數(shù)組,則傳遞此類數(shù)組的正確方法是使用指向其第一個元素的指針,并使用附加參數(shù)提供的具體大小
void foo(char p[], unsigned plen);
實際上,在許多情況下,能夠處理運行時大小的數(shù)組非常有用,這也有助于該方法的普及。許多C開發(fā)人員根本沒有遇到(或從未認識到)處理固定大小的數(shù)組的需要,因此對適當?shù)墓潭ù笮〉募夹g(shù)仍然沒有任何了解。
但是,如果數(shù)組大小固定,則將其作為指向元素的指針傳遞
void foo(char p[])
這是一個主要的技術(shù)級錯誤,不幸的是,如今這些錯誤相當普遍。在這種情況下,指針數(shù)組技術(shù)是一種更好的方法。
可能會阻止采用固定大小的數(shù)組傳遞技術(shù)的另一個原因是,幼稚方法在動態(tài)分配數(shù)組的類型化方面占主導地位。例如,如果程序調(diào)用類型的固定陣列char[10](如在你的例子),平均顯影劑將malloc此類陣列如
char *p = malloc(10 * sizeof *p);
該數(shù)組不能傳遞給聲明為
void foo(char (*p)[10]);
這使普通開發(fā)人員感到困惑,并使他們放棄了固定大小的參數(shù)聲明,而無需進一步考慮。但實際上,問題的根源在于幼稚的malloc方法。malloc上面顯示的格式應保留給運行時大小的數(shù)組。如果數(shù)組類型具有編譯時大小,則更好的方法malloc如下所示
char (*p)[10] = malloc(sizeof *p);
當然,這可以很容易地傳遞給上面聲明的 foo
foo(p);
編譯器將執(zhí)行正確的類型檢查。但是,這再一次給一個沒有準備的C開發(fā)人員帶來了太多混亂,這就是為什么您不會在“典型”的日常代碼中經(jīng)??吹剿脑颉?/p>

TA貢獻1784條經(jīng)驗 獲得超9個贊
我想補充一下AndreyT的答案(以防萬一有人偶然在此頁面上尋找有關(guān)此主題的更多信息):
當我開始更多地使用這些聲明時,我意識到C中與它們相關(guān)的主要障礙(顯然不是C ++)。在某些情況下,您想給調(diào)用者一個指向已寫入緩沖區(qū)的const指針,這是很常見的。不幸的是,在C中聲明這樣的指針時,這是不可能的。換句話說,C標準(6.7.3-第8段)與以下內(nèi)容不一致:
int array[9];
const int (* p2)[9] = &array; /* Not legal unless array is const as well */
這種約束似乎在C ++中不存在,這使這些類型的聲明更加有用。但是對于C語言,每當您要使用指向固定大小緩沖區(qū)的const指針時,都必須回退到常規(guī)指針聲明(除非緩沖區(qū)本身被聲明為const開頭)。您可以在此郵件主題中找到更多信息:鏈接文本
在我看來,這是一個嚴格的約束,這可能是人們通常不使用C聲明這樣的指針的主要原因之一。另一個事實是,大多數(shù)人甚至都不知道您可以這樣聲明一個指針: AndreyT指出。

TA貢獻1869條經(jīng)驗 獲得超4個贊
簡而言之,C不會那樣做。類型數(shù)組T作為指針傳遞給T該數(shù)組中的第一個指針,僅此而已。
這允許一些很酷而優(yōu)雅的算法,例如使用類似以下表達式的數(shù)組循環(huán)
*dst++ = *src++
缺點是大小的管理取決于您。不幸的是,不認真執(zhí)行此操作還導致了C編碼中的數(shù)百萬個錯誤和/或惡意利用的機會。
與您在C語言中所要求的最接近的是傳遞一個struct(按值)或一個指向一個(按引用)的指針。只要在此操作的兩邊使用相同的結(jié)構(gòu)類型,則分發(fā)引用的代碼和使用引用的代碼都將與要處理的數(shù)據(jù)大小一致。
您的結(jié)構(gòu)可以包含您想要的任何數(shù)據(jù);它可能包含大小明確定義的數(shù)組。
但是,沒有什么能阻止您或功能不強或惡意的編碼器使用強制轉(zhuǎn)換來欺騙編譯器,以將您的結(jié)構(gòu)視為不同大小的結(jié)構(gòu)之一。C的設(shè)計幾乎包括了完成這種事情的能力。
- 3 回答
- 0 關(guān)注
- 749 瀏覽
添加回答
舉報