3

这是原型:

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

首先我不确定我是否必须返回一些东西,因为例如当我使用 memset 时

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 指针上的字符中 - 在我的 while 上使用什么条件来确定它在 '\0' 字符之前停止

编辑:我想知道有没有办法在不强制转换的情况下执行此功能?

4

6 回答 6

10

如何将 int c 复制到我的 void b 指针上的字符中

您将 void 指针转换为无符号字符指针:

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;
于 2013-09-17T13:56:42.850 回答
2

函数经常返回值的原因是向调用函数返回错误状态。在与内存相关的函数中,它通常与您的结果应该是相同的指针(包括 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 *bNULL,您将遇到分段错误。

传递 没有错void *,除了函数的意图可能不像传递指向特定数据类型的指针那样清晰。确保将其转换为内部有效的东西。同样通过这种方式,该函数可以很容易地将任何内存设置为特定的十六进制值(通过 char)或全 0。

在这种情况下,似乎b应该转换为与您尝试复制到其中的值相同的类型,即int; 但是,那么len参数变得不清楚,它是以字节为单位的大小还是c应该复制到b指针的次数?

由于在您main()将 a 复制char到该内存位置,因此最好将您更改c为 a char,将您b转换为 achar*len以字节或次数为单位的长度c应复制到*b. 避免歧义。

您编写它的方式,它将复制c指定的次数len或直到您遇到空字符,以最短/最快者为准。没关系,如果这是你的意图。

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);
    }
}
于 2013-09-17T15:01:33.390 回答
2

指针算法基于将指针偏移它指向的类型的大小。在开始增加该指针之前,您应该将其转换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;
}

另请注意,它返回指向内存区域 s 的指针,因此您应该返回原始指针(在开始递增它之前)。memset

于 2013-09-17T14:02:21.920 回答
1
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);
}
于 2013-09-17T14:01:52.903 回答
0

您可以使用 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)
于 2013-12-20T17:14:38.180 回答
-1

我尝试了一种这样的实现:

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

        while(len--)
            *s++ = c;
    }
于 2014-02-06T10:30:13.707 回答