2010-01-22 117 views
4

我試圖將一個char*的數組返回給一個函數。我簡化了我的代碼到一個測試用例,該用例克隆了一個char數組,而不是包含chars的指針指向這些chars。返回一個char指針數組

/* 
* code.c 
*/ 
#include <stdio.h> 

char* makePointerCopy(char cIn[]); 

int main() { 
    char cTest[] = {'c', 't', 's', 't'}; 
    char* cPTest[] = makePointerCopy(cTest); 
    printf("%p %c", cPTest, *cPTest); 
    fflush(stdout); 
    return 0; 
} 

char* makePointerCopy(char cIn[]) { 
    char* cOut[sizeof(cIn)/sizeof(cIn[0])]; 
    int iCntr; 

    for (iCntr = 0; iCntr < sizeof(cIn)/sizeof(cIn[0]); iCntr++) 
     cOut[iCntr] = cIn + iCntr; 

    return cOut; 
} 

一對夫婦的警告放在一邊的,這就是編譯器必須說這個代碼片段:

無效初始化(在char* cPTest[] = makePointerCopy(cTest);

爲什麼會出現這種情況?

+1

此代碼還有另一個重要問題:'char * cOut [sizeof(cIn)/ sizeof(cIn [0])]];'不起作用。參數列表中的簡單'char cIn []'不會包含數組的大小信息。你需要類似'template ...(char(&cIn)[N])',那麼N將匹配元素的數量。可選:使用'char * start,char * end'來傳遞數組。 – gimpf 2010-01-22 15:28:10

+0

如果我將iSize傳遞給函數,那麼在makePointerCopy調用之前會把這個放在main()塊中嗎? 'int iSize = sizeof(cTest)/ sizeof(cTest [0]);' – Pieter 2010-01-22 15:35:01

回答

5

因爲makePointerCopy返回char*,而不是char*[]

您應該能夠到該行更改爲:

char* cPTest = makePointerCopy(cTest); 

更具體地說,你會得到錯誤信息,而不是一些關於類型的原因,就是數組的初始化需要在編譯時常量。

http://bytes.com/topic/c/answers/215573-invalid-initializer

即使聲明是無法以文件 範圍,它會在這兩個C90 和C99是非法的。 C90需要編譯時間 用於自動 和寄存器陣列的常量初始化程序。並且C90和 C99都要求字符數組爲 ,使用a)字符串文字 或b)括號括起來的初始化程序 列表進行初始化。

不過,類型不匹配是這裏的實際問題。

2

您需要返回char **char *[]

特別是如果你想makePointerCopy返回「的char*數組,那麼你需要真正迴歸這樣的陣列。現在你返回一個指向char,或」 char*」。

線有問題的代碼試圖分配makePointerCopy的結果,該結果返回char*char*[]雖然在技術上C是可以的,並且編譯器仍然會產生一個結果,但編譯器基本上告訴你它產生的結果可能不是實際上按照你的預期執行。

3

在那l ine,你正試圖給一個char *數組賦一個char *。簡而言之,它們是不同的類型。

+0

所以我需要改變返回類型?我該如何改變它?我試過'char * []'但是會產生大量的錯誤和警告。 – Pieter 2010-01-22 15:29:38

+0

Pieter - 請參閱我的答案,瞭解要更改的示例。 – danben 2010-01-22 15:32:32

+0

char **應該這樣做,如果我沒記錯的話。將cPTest的類型也更改爲char **。 – Aaron 2010-01-22 15:37:25

2

因爲您的函數在將其分配給char*[]時返回char*。 C可能有一個相當弱的類型系統,但有些事情不應該完成:-)

0

函數返回一個char *而不是char [] *。

0

char *是一個指向單個字符在那裏,因爲你需要char **這是一個指向數組的指針或char *

2

讓我們先從警告。您宣佈:

char* cPTest[] 

英文: 「cPTest是數組的指針爲char

char* makePointerCopy(char cIn[]); 

英文:「makePointerCopy()需要字符,並返回數組一個指向字符的指針

所以你試試將「指針指向字符」分配給「指向字符的指針數組」。你能看到問題嗎?我建議在做任務之前仔細檢查類型。

這就是說,你真正想要的是聲明makePointerCopy()一個「指針的指針爲char」迴歸:

char **makePointerCopy(char cIn[]); 

,因爲在最後,你將指針返回的第一個元素返回數組。

另一個重點:你聲明你「cOut」作爲函數的局部變量。

char* makePointerCopy(char cIn[]) { 
    char* cOut[sizeof(cIn)/sizeof(cIn[0])]; 

    ... /* cOut can ONLY be used within the function! */ 

    return cOut; // <-- The address returned point to a 
        //  block of memory that is no longer valid 
        //  after the end of the function 
} 

請記住,一旦函數終止,局部變量會自動失效。爲了「保護」它,你可以聲明它static

char* makePointerCopy(char cIn[]) { 
    static char* cOut[sizeof(cIn)/sizeof(cIn[0])]; 

    ... /* cOut will survive the end of the function */ 

    return cOut; // <-- The address can be returned 
} 

請注意,您必須遵守紀律時返回這種類型的值。

作爲一種替代方案,只要您不再需要它,您就可以記住free(),您可以使用malloc()來分配需要的空間。

+0

我想我開始明白了。至於局部變量:cOut指向一個不是在'makePointerCopy'中產生的變量,因此我應該是安全的,對吧?無論如何,有沒有辦法讓C擦除特定的局部變量? – Pieter 2010-01-22 15:54:47

+0

你不安全,因爲cOut *在函數內被聲明,並且在返回後無效使用它。您可以將其聲明爲「靜態」以允許返回其地址。我要編輯答案來展示這一點。 – 2010-01-22 16:11:26

1

所有其他的答案是正確的,但似乎有相當多的其他問題與您的代碼:

char* cOut[sizeof(cIn)/sizeof(cIn[0])]; 

我相信你想的sizeof(CIN)返回的內存佔用量cIn數組中的元素。這是不正確的。在這種情況下,sizeof(cIn)將返回系統上指針的大小,通常爲4或8個字節。 sizeof(cIn [0])將返回一個字符的大小,即1個字節。通常沒有辦法在C中發現數組的大小,所以恐怕你必須將這個大小傳遞給你的函數。

還要記住,makePointerCopy返回一個指向靜態分配的內存塊的指針。該內存基本上是makePointerCopy的局部變量,並且在makePointerCopy完成它的工作時將被釋放。換句話說,makePointerCopy會返回一個指向無效內存的指針。