簡體   English   中英

使用我自己的strcopy函數時變空

[英]Getting empty when using my own strcopy function

void strcopy(char *src, char *dst) {
  int len = strlen(src) - 1;
  dst = (char*)malloc(len);
  while(*src){
    *dst = *src;
     src++; dst++;
  }
  *dst = '\0';
}
int main() {
  char *src = "hello";
  char *dst = "";
  strcopy(src, dst);
  printf("strcpy:%s\n", dst);
  return 0;
}

Output:
strcpy:

誰能解釋我的strcopy函數出了什么問題? 但是如果在main執行malloc ,我將得到正確的輸出。 困惑,因為malloc僅在堆中分配內存?

就你而言

  strcopy(src, dst);

dst本身通過值傳遞。 您不能在函數內部分配內存,並且不能期望內存會在調用方函數中反映出來

如果要在strcopy()內存分配給dst ,則需要

  • 將指針傳遞給dst
  • 或者,您也可以從函數中return新分配的dst並將其收集回調用方的dst中。

    但是,請記住,當您自己分配內存時,有責任free()它。

否則,您可以在調用方( main() )函數內部的dst分配內存,然后將已經分配的dst傳遞給函數以執行復制作業。 恕我直言,這種方法與庫函數strcpy()更相似,因為API本身不處理目標內存的分配。


注意::在代碼中表示

 int len = strlen(src) - 1;

您面臨邏輯錯誤。 應該是

 int len = strlen(src) + 1;

也要累積終止null。

那里有一些問題:

  1. strcopy執行此strcopy

     dst = (char*)malloc(len); 

    您將使用新的指針覆蓋 dst參數中的指針。 這有沒有影響對所有 dst的主要變量,因為它的價值 ,而不是對它的引用,被傳遞到strcopy 因此,當您打印出maindst指向的字符串時,它自然不變,並且仍然是""

  2. 您沒有為副本分配足夠的內存。 您已經完成:

     int len = strlen(src) - 1; dst = (char*)malloc(len); 

    它分配的兩個字節太少 您需要+ 1 ,而不是- 1 :源字符串( strlen(src) )中的字符數, 再加上一個用於終止空字符。

  3. 您正在分配從未釋放的內存。

    請記住,它是這樣寫的:

    正如你們malloc ,所以必向你free

#2不容易受到使用固定+ 1 ,而不是- 1

#1有多種固定方式:

  1. 您可以讓您的strcopy為副本分配內存,然后不傳遞dst並讓它返回分配的指針。 它的文檔會說它做了一個分配,要求調用者將其釋放。 例如:

     char * strcopy(char *src) { int len = strlen(src) + 1; char * dst = (char*)malloc(len); for (p = dst; *src; ++p, ++src) { *p = *src; } *p = '\\0'; return dst; } int main() { char *src = "hello"; char *dst = strcopy(src); printf("strcopy:%s\\n", dst); free(dst); // <== note return 0; } 
  2. 您可以寫入內存maindst指向,但是您需要確保分配足夠的內存。 通常,在C語言中,如果要將緩沖區傳遞到應該寫入緩沖區的函數中,則還傳遞緩沖區的大小,以便函數知道在哪里停止。

您的代碼中有兩件事是錯誤的。

首先,您的strcopy()函數將strlen(src) - 1字符分配給dst ,然后將strlen(src) + 1字符復制到其中。 這給出了不確定的行為。

其次,你main()通過其本地dst由值(字符串文字中第一個字符的即地址"" 。改變的價值dststrcopy()因此對價值沒有影響dstmain()兩個變量(在main()strcopy() )具有相同的名稱這一事實不會改變這一點。

總結其他人的意見和建議,您的代碼可以如下:

void strcopy(char *src, char **_dst) {
  int len = strlen(src) + 1;
  char *dst = malloc(len);
  *_dst= dst;
  while(*src){
    *dst = *src;
     src++; dst++;
  }
  *dst = '\0';
}
int main() {
  char *src = "hello";
  char *dst;
  strcopy(src, &dst);
  printf("strcpy:%s\n", dst);
  return 0;
}

這是您要尋找的:

void strcopy(char **src, char **dst) {
  int len = strlen(*src) + 1;
  *dst = (char*)malloc(len);
  int j;
  for(j=0;j<strlen(*src);j++)
  {
    dst[j] = src[j];
  }
  dst[j] = '\0';
}

int main() {
  char *src = "hello";
  char *dst = "";

  strcopy(&src, &dst);
  printf("strcpy:%s\n", dst);
  return 0;
}

函數參數是函數的局部變量。 函數處理其參數的副本。 因此,函數中參數的任何更改都不會影響相應參數的原始值。

因此,例如,函數strcopy此語句

dst = (char*)malloc(len);

不會更改main中定義的參數dst

char *dst = "";

如果您確實想編寫一個名為strcopy的函數,則該函數應處理已分配的數組。 否則,如果函數本身創建源字符串的新副本,則該函數應像strdup這樣命名。

此外,您的函數是錯誤的,因為當源字符串為空,因此strlen(src)等於0時,它可以嘗試分配負的內存大小的內存。在任何情況下,它分配的內存都少於所需的內存。

int len = strlen(src) - 1;
dst = (char*)malloc(len);

該功能可以通過以下方式定義

char * strcopy( char *dst, const char *src ) 
{
    char *p = dst;

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

    return dst;
}

叫像

int main( void ) 
{
    char *src = "hello";
    char dst[6];

    printf( "strcpy:%s\n", strcopy( dst, src ) );

    return 0;
}

還應考慮到您不能在C(和C ++)中更改字符串文字。 任何試圖更改字符串文字的嘗試都會導致程序的行為未定義。

因此,您可能不會像例如聲明變量dst

char *dst = "A string literal";

並調用函數strcopydst作為第一個參數傳遞給上述程序。

如果要創建源字符串的副本,則可以通過以下方式定義函數

char * strdup( const char *src ) 
{
    char *dst = malloc( ( strlen( src ) + 1 ) * sizeof( char ) );

    if ( dst )
    {
        char *p = dst;
        while ( ( *p++ = *src++ ) );
    }

    return dst;
}

叫像

int main( void ) 
{
    char *src = "hello";
    char *dst;

    dst = strdup( src ) ;
    printf( "strcpy:%s\n", dst );

    free( dst );

    return 0;
}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM