1. 实现一个memcpy函数。
先看下标准memcpy()的解释:
void *memcpy(void *dst, const void *src, size_t n);
//If copying takes place between objects that overlap, the behavior is undefined.
事实上所说的陷阱也在于此,自己动手实现memcpy()时就需要考虑地址重叠的情况。
另外,标准库也提供了地址重叠时的内存拷贝函数:memmove(),那么为什么还要考虑重写memcpy()函数呢?
因为memmove()函数的实现效率问题,该函数把源字符串拷贝到临时buf里,然后再从临时buf里写到目的地址,增加了一次不必要的开销。
void* Memcpy(void *dest, const void *src, size_t n)
{
if(dest == NULL || src == NULL)
return NULL;
const char *psrc = (char *)src;
char *pdest = (char *)dest;
size_t i;
if((psrc < pdest) && (psrc + n > pdest))
{
i = n;
while(i > 0) //注意i类型是size_t,无符号整形,所以不能用i>=0来判断
{
pdest[i-1] = psrc[i-1];
i--;
}
}
else
{
i = 0;
while(i < n)
{
pdest[i] = psrc[i]; i++
}
}
return dest;
}
int main()
{
char buf[100] = "abcdefghijk";
Memcpy(buf+2, buf, 5);
printf("%s\n", buf);
return 0;
}
2. 实现一个atoi的函数
double atof(char s[])
{
double val = 0.0;
int i,v_pow,sign,e_sign,e_pow;
for (i = 0; isspace(s[i]); i++) // skip the white space
;
sign = (s[i] == '-') ? -1 : 1;
if (s[i] == '-' || s[i] == '+')
i++;
for (val = 0; isdigit(s[i]); i++)
val = val * 10 + (s[i] - '0');
if (s[i] == '.')
i++;
for (v_pow = 1; isdigit(s[i]); i++)
{
val = val * 10 + (s[i] - '0');
v_pow *= 10;
}
if (s[i] == 'e' || s[i] == 'E') // handle scientific notation
i++;
e_sign = (s[i] == '-') ? -1 : 1;
if (s[i] == '-' || s[i] == '+')
i++;
for (e_pow = 0; isdigit(s[i]); i++)
e_pow = e_pow * 10 + (s[i] - '0');
e_pow *= e_sign;
return sign * (val * pow(10, (double)e_pow)) / v_pow;
}
double atoi(char s[])
{
return (int)atof(s);
}
int main()
{
char s[] = "-45.67e-100";
double d = atof(s);
printf("%g\n", d);
char ss[] = "-45e4";
int i = atoi(ss);
printf("%d\n", i);
return 0;
}