簡體   English   中英

在C中創建我自己的memset函數

[英]create my own memset function in c

這是原型:

void *memset(void *s, int c, size_t n)

首先,我不確定我是否必須返回某些東西,因為當我使用記憶集時,例如

memset(str, 'a', 5);

代替

str = memset(str, 'a', 5);

這是我的代碼所在的位置:

void *my_memset(void *b, int c, int len)
{
    int i;

    i = 0;
    while(b && len > 0)
    {
        b = c;
        b++;
        len--;
    }
    return(b);
}

int main()
{
    char *str;

    str = strdup("hello");
    my_memset(str, 'a', 5);
    printf("%s\n", str);
}

我不想在此函數中使用數組,以便更好地理解指針和內存,所以我沒有得到兩件事:-如何將int c復制到我的void b指針上的一個字符中-在我使用的同時要確保什么條件它在'\\ 0'字符之前停止

編輯:我想知道是否有一種無需鑄造就可以完成此功能的方法?

如何將int c復制到我的void b指針上的字符中

您將void指針轉換為無符號char指針:

void  *my_memset(void *b, int c, int len)
{
  int           i;
  unsigned char *p = b;
  i = 0;
  while(len > 0)
    {
      *p = c;
      p++;
      len--;
    }
  return(b);
}

我在使用什么條件來確保它在'\\ 0'字符之前停止

memset必須信任傳入的長度。memset需要在一般的內存上工作,而不僅僅是終止於0的字符串-因此不應進行此類檢查。

如果您仍然需要檢查0字節。 你會做

if (*p == 0) //or if(!*p )
     break;

指針算術基於將指針偏移其指向的類型的大小。 在開始增加該指針之前,應將其從void*轉換為char / unsigned char指針:

void* my_memset(void *s, int c, size_t len) {
    unsigned char *dst = s;
    while (len > 0) {
        *dst = (unsigned char) c;
        dst++;
        len--;
    }
    return s;
}

還要注意, memset 返回指向存儲區s的指針 ,因此您應該返回原始指針(在開始遞增它之前)。

函數通常返回值的原因是為了將錯誤狀態返回給調用函數。 在與內存相關的函數中,它通常與結果應包含的指針相同(包括NULL)。 在您的示例中,您可能不想使用my_memset函數的返回值,但這通常是因為它可以包含在代碼評估中(為此想不到一個更好的詞),例如

if(!my_memset((void *)str, 'a', 5))
{
    printf("An error occurred in my_memset()\n");
}

或在宏中,例如,返回指向復制char的內存末尾的指針:

#define INIT_MEM_PTR_END(a,x) (my_memset((void *)&(a), (x), sizeof(a)) + sizeof(a))

這可能不是一個好例子(如果a已經是指針等,還會加上潛在的問題,等等),但是它表明您可以重用結果,而不必為此寫另外幾行代碼來評估結果,因此上。

在取消引用指針之前,還應該檢查指針。 例如,如果void *b為NULL,則將出現分段錯誤。

傳遞void *沒什么不對,除了函數的意圖可能不如傳遞指向特定數據類型的指針時那樣明確。 確保將其投射到內部有效的東西上。 同樣,通過這種方式,該函數可以很容易地將任何內存設置為特定的十六進制值(通過char)或全0。

在這種情況下,似乎b應該轉換為與您要復制到其中的值相同的類型,即int 但是, len參數變得不清楚,是以字節為單位還是將c復制到b指針的次數?

由於在main()中將一個char復制到該內存位置,因此最好將c更改為char ,將b轉換為char*然后將len的長度以字節為單位或將c設為復制到*b 避免歧義。

編寫方式將復制len指定的c次或直到遇到空字符(以最短/最快的時間為准)。 如果那是您的意圖,那很好。

void *my_memset(void *b, char c, int len)
{
    char *b_char = (char *)b;

    if (b == NULL) return NULL;

    while(*b_char && len > 0)
    {
        *b_char = c;
        b_char++;
        len--;
    }

    return b; //as this pointer has not changed
}

int main()
{
    char *str;

    str = strdup("hello");
    if (!my_memset((void *)str, 'a', 5))
    {
        printf("An error occurred in my_memset()\n");
    }
    else
    {
        printf("%s\n", str);
    }
}

您可以使用Duff設備來獲得更好的性能。

#define DUFF_DEVICE_8(aCount, aAction) \
do { \
int count_ = (aCount); \
int times_ = (count_ + 7) >> 3; \
switch (count_ & 7){ \
case 0: do { aAction; \
case 7: aAction; \
case 6: aAction; \
case 5: aAction; \
case 4: aAction; \
case 3: aAction; \
case 2: aAction; \
case 1: aAction; \
} while (--times_ > 0); \
} \
} while (0)
void   *my_memset(void *b, int c, int len)
{
  if (b == NULL || len <= 0)
      return b;
  unsigned char *ptr = b;
   while(*ptr != '\0' && len--)
    {
      *ptr++ = (unsigned char)c;
    }
  return(b);
}

我嘗試了這樣的一種實現:

    void memset(void *b, int c, int len)
    {
       char *s = b;

        while(len--)
            *s++ = c;
    }

暫無
暫無

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

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