这是原型:
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指针上的字符中 - 在我的时间使用什么条件,以确保它在'\ 0'字符
之前停止编辑:我想知道有没有方法可以在没有强制转换的情况下执行此功能?
答案 0 :(得分:6)
如何将int c复制到我的void b指针上的字符
将void指针转换为unsigned 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);
}
memset必须信任传入的长度.memset需要处理一般的内存,而不仅仅是一个0终止的字符串 - 所以不应该进行这样的检查。我可以使用什么条件来确保它在'\ 0'char
之前停止
如果你反正需要检查一个0字节。你会做的
if (*p == 0) //or if(!*p )
break;
答案 1 :(得分:1)
指针算法基于将指针偏移其指向的类型的大小。在开始递增指针之前,您应该将其从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
返回指向内存区域的指针,因此您应该返回原始指针(在开始递增之前)。
答案 2 :(得分:1)
函数经常返回值的原因是将错误状态返回给调用函数。在与内存相关的函数中,它通常与结果应该是相同的指针(包括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
1}}到char*
并使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);
}
}
答案 3 :(得分:1)
您可以使用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)
答案 4 :(得分: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);
}
答案 5 :(得分:0)
我试过这样一个实现:
void memset(void *b, int c, int len)
{
char *s = b;
while(len--)
*s++ = c;
}