2012-03-16 156 views
0

我想知道如何分配一個函數中的字符指針使用雙指針和寫入指針的內存。如何在C函數中使用雙指針分配內存?

我試着寫下面的代碼,但它崩潰了。這個錯誤是什麼?

#include <stdio.h> 
void myfunc(const char* src, char** dest) 
{ 
    *dest = (char*)malloc(200); 
    while(*(*dest++) = (*src++ != '\0')); 
    *(*(++dest)) = '\0'; 
} 
void main() 
{ 
char* src = "hello"; 
char* dest = null; 
myfunc(src, &dest); 
printf("%s\n",dest); 
} 
+0

'dest'中沒有數據。首先用有效數據填充它,並確保它是空的,然後執行'=='操作。 – Mahesh 2012-03-16 13:17:29

+0

你想完成什麼?它看起來像你試圖比較每個字符而沒有邊界檢查,並且你也不會在'malloc'後面設置任何東西。 – Joe 2012-03-16 13:17:52

+1

遞增'char **'會使它指向下一個char *',而不是下一個'char'。 – sidyll 2012-03-16 13:18:08

回答

3

你寫一個比較循環,而不是一個副本環路(「==‘VS’=」),並且您遞增,當你寫了錯誤的指針:

while(*(*dest++) == *src++); 

(附加行:

*(*(++dest)) = '\0'; 

是了最新除了這個問題我不知道我想嘗試解析,在所有這不是解決問題的一部分,見d。下面藏密壇城藝術)

來獲取正確的最簡單的方法可能是:

char *tgt = *dest; 
while ((*tgt++ = *src++) != '\0') 
    ; 

我們可以分階段糾正你的代碼(我這樣做是這樣):

static void myfunc(const char* src, char** dest) 
{ 
    *dest = (char *)malloc(200); 
    char *tgt = *dest; 
    while ((*(tgt++) = *(src++)) != '\0') 
     ; 
} 

這parenthesises循環中的表達式完全。我們現在可以替代*desttgt

static void myfunc(const char* src, char** dest) 
{ 
    *dest = (char *)malloc(200); 
    char *tgt = *dest; 
    while ((*((*dest)++) = *(src++)) != '\0') 
     ; 
    printf("1: %s\n", tgt); 
} 

而這種打印1: hello,但主程序在複製的字符串末尾打印一個空行,因爲你已經修改了*dest因此它指向NUL '\0'。所以,你需要這樣做:

static void myfunc(const char* src, char** dest) 
{ 
    *dest = (char *)malloc(200); 
    char *tgt = *dest; 
    while ((*((*dest)++) = *(src++)) != '\0') 
     ; 
    printf("1: %s\n", tgt); 
    *dest = tgt; 
} 

然後main()將打印正確的答案。但是,如果你用tgt('目標'的縮寫;我通常使用dst作爲目的地,但這太接近你的dest),那麼你最好避免增加*dest的複雜性。

事實上,你應該考慮使用:

#include <string.h> 

... 
strcpy(*dest, src); 

複製的字符串。使用strcpy()可能會更好,如「更快」和「更簡單」並且明確無誤。


此外,你應該有:

#include <stdlib.h> 

申報malloc()

而對於main()正確的返回類型爲int

int main() 
{ 
    ... 
    return(0); 
} 

在C99,回報是(遺憾)可選的零(成功)將假設,如果它是丟失;這匹配C++ 98的行爲。在早期版本的C中,返回不是可選的。

+0

我想知道如何複製沒有strcpy。在相同的功能和理解的探索。 – user1274081 2012-03-16 13:26:28

0

這個小問題有很多問題,我不知道從哪裏開始......總結起來,你已經使得代碼變得不必要的複雜,因此最終導致了很多bug。

事情解決,使這個代碼編譯:

  • 除非這是代碼用於嵌入式系統,或者除非你正在寫一個操作 系統,主要必須返回int類型。
  • NULL是C中的大寫常量,可在stddef.h庫中找到。
  • malloc函數在stdlib.h中找到,必須包含它。

嚴重的bug:

  • 決不強制轉換的malloc的結果。更多信息在C FAQthis SO post
  • 總是釋放由malloc分配的內存。
  • 將* srC++!='\ 0'的布爾結果(true/false)賦值給一個字符。

廣泛認可壞&危險的做法,導致錯誤:

  • 始終聲明指向字符串字面量爲const。
  • 不要在條件內使用賦值。 (MISRA-C:2004 13.1)。
  • 切勿在複雜表達式中使用++運算符(MISRA-C:2004 12.13)。
  • 切勿在包含循環語句的行的末尾放置分號。 (MISRA-C:2004 14.9)
  • 切勿使用任何沒有大括號的語句{}(MISRA-C:2004 14.8)。

可憐的風格:

  • 的main()應該總是返回。
  • 避免「幻數」,特別是將參數傳遞給malloc時。
  • 總是檢查malloc()的結果。

有用的提示:

  • 釋放calloc將所有分配的內存爲零,不像malloc的。如果您使用calloc,則不必手動將它們設置爲零。

固定碼:

#include <stdio.h> 
#include <stddef.h> 
#include <stdlib.h> 

#define DYNAMIC_BUF_SIZE 200 

void make_string (const char* src, char** dest) 
{ 
    *dest = calloc(DYNAMIC_BUF_SIZE, sizeof(char)); 

    if(*dest == NULL) 
    { 
    /* error handling here */ 
    } 

    char* dst = *dest; 
    *dst = *src; 

    while(*src != '\0') 
    { 
    dst++; 
    src++; 
    *dst = *src; 
    } 
} 

void delete_string (char* str) 
{ 
    free(str); 
} 

int main() 
{ 
    const char* src = "hello"; 
    char* dest = NULL; 

    make_string (src, &dest); 
    printf("%s\n",dest); 
    delete_string(dest); 

    return 0; 
} 

編輯:沒有strcpy的新版(),由OP的要求。

0
//It seems that you don't understand the nature of char* and char**. 
char *str = "hello! I am from China and i want to make friends with foreigners"; 
char **ptr = {"hello!","i want to learn spoken English","[email protected]"}; 
//Allocate memory for a char** variable. Two steps as follows: 
int length[3] = {6,31,16}; 
char **ptr2 = new char*[3]; 
for(int i = 0;i < length[i];i++) 
    *(ptr2 + i) = new char [length[i]]; 
//delete according to a reverse order.