2009-10-15 86 views
2

我想知道如果你能幫我解決C字符串問題,我不太明白。我有一個函數,我發送3個字符指針。在這個函數中,char指針被正確地移位和修改。但是,當我返回到它們被調用的主函數時,所述函數不會改變。我過去的價值是錯誤的嗎?下面是我的代碼示例:在C中傳遞和修改char指針之間的混淆(參考與值)

int main(void) 
{ 
    LPSTR path = (char*)malloc(strlen(START_PATH)); 

    strcpy(path, START_PATH); 

    char* newstr = (char*)malloc(PATH_SIZE); 

    TrimVal(path, "*.*", newstr); 

    //Do Stuff 

    return 0; 
} 

void TrimVal(char* modify, char* string, char* newstr) 
{ 
     newstr[0] = '\0'; 

     modify = strncat(newstr, modify, (strlen(modify) - strlen(string))); 

     return; 
}  

注:假設PATH_SIZE是一個大小值,START_PATH是一個字符數組

+0

@sgm:沒有對這裏的標準。也許你對Windows數據類型的使用產生了負面影響? – 2009-10-15 15:39:03

+0

我應該指出main()中的前兩行不會做你認爲他們做的事。首先,sizeof(START_PATH)實際上返回sizeof(char *),因爲sizeof(變量)實際返回變量_type_的大小。你想在第一行用strlen替換sizeof。其次,當你寫path = START_PATH時,你正在用覆蓋你指向START_PATH指針的指針。而不是簡單地複製指針,你需要使用strcpy。 – 2009-10-15 15:52:31

+0

現在,我在帖子中修復了源代碼。 – 2009-10-15 15:55:17

回答

6

在這一過程中

modify = strncat(newstr, modify, (strlen(modify) - strlen(string))); 

要修改指針,而不是指針指向的內容。

當您將path傳遞給TrimVal時。它將通過path的存儲位置,例如0x12345

當您執行modify =時,您說的是將本地變量modify更改爲新的內存位置,例如, 0x54321

當您返回到主,它只有一個指向0x12345,當它看起來那裏,沒有任何改變。

您可以通過執行

{ 
... 
TrimVal(&path, "*.*", newstr); 
... 
} 

void TrimVal(char** modify, char* string, char* newstr) 
{ 

     newstr[0] = '\0'; 

     *modify = strncat(newstr, *modify, (strlen(*modify) - strlen(string))); 

     return; 

}  
+0

你擊敗了我的答案。不公平:P – wheaties 2009-10-15 15:28:13

+0

應該是 * modify = strncat(newstr,* modify,(strlen(* modify) - strlen(string))); – 2009-10-15 15:38:51

+0

需要注意的是,如果您在調用'TrimVal()'的代碼沒有其他更改的情況下執行這些更改,那麼位於'path'中的指針將會丟失,現在由於從堆中分配了內存泄漏,所以存在內存泄漏。 – 2009-10-15 20:01:42

0

如果你希望你的char *變量的函數修改很容易地解決你的問題,你想通過引用傳遞,你需要將它傳遞爲char * 。記住,你是通過引用傳遞指針,所以需要有額外的間接層(通過炭不按引用傳遞的東西 - 一個字符)

0

C沒有真正有一個pass-引用。你在這裏做的是通過價值指針。 C中的字符串由指向char的指針表示。因此,在函數TrimVal中,您可以修改字符串(即指向數據)的內容,但不能修改指針本身。

strncat修改第一個參數的內容並返回相同的值。

如果你想內改變路徑的價值TrimVal,你應該通過一個指針的指針,像這樣:

... 

TrimVal(path, "*.*", newstr); 

... 

void TrimVal(char** modify, char* string, char* newstr) 

{ 
    newstr[0] = '\0'; 
    *modify = strncat(newstr, *modify, (strlen(*modify) - strlen(string))); 
    return; 
} 
+1

應該是* modify = strncat(newstr,* modify,(strlen(* modify) - strlen(string))); – 2009-10-15 15:39:23

+0

好的。在代碼中修復。 – 2009-10-20 00:32:53

1
void TrimVal(char* modify, char* string, char* newstr) 

改變的modifystring值,或TrimVal()函數內的newstr對調用函數中的變量沒有影響。

改變的modifystring,或newstrTrimVal()函數內部的內容將在上調用函數中的變量中得到反映。

所以

void TrimVal(char* modify, char* string, char* newstr) 
{ 
    newstr[0] = '\0'; /* will be reflected in the calling function */ 
    modify = "a new string"; /* won't be reflected */ 
} 

我想你的函數,用的代碼小空地上,可以做你想做的。

噢......並且您有一個內存泄漏,path變量:您malloc有一定的空間,然後立即通過爲path變量指定一個不同的值來丟失該空間的地址。

0

我發現前兩個語句有問題。您將路徑聲明爲指針char併爲其分配存儲在此地址持有者中的內存。在您的下一個語句中,您將更改路徑中的值,並將其指向char數組的開始START_PATH。你分配的內存現在丟失了。

另外,strncat不會調用malloc進行連接。預計您將傳遞足夠大的緩衝區來容納concat,這是潛在的安全風險(緩衝區溢出)。

1

除了在這個線程提出的許多其他好的幾個點:

LPSTR path = (char*)malloc(strlen(START_PATH)); 

如果這是C,你不應該投的malloc返回值。 (參見C FAQ 7.7b

更重要的是,strlen不包括終止於它的計算因此,存儲器path\0到是一個字符短,所需存儲器量的保持START_PATH加上\0因此:。

strcpy(path, START_PATH); 

通過寫一個過去的記憶指向path調用未定義的行爲。

0

只是一個關於你的鑄造的malloc C的返回類型風格的註釋所有。投射時可以隱藏錯誤。

這將是一個更好的風格。

包括stdlib.h,並嘗試並以獨立於類型的方式調用malloc。

char *ptr_char = NULL; 

ptr_char = malloc(sizeof(*ptr_char)); 

希望這有助於