3 回答

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

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

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