我写的memchr:
1 void *memchr(const void *buf, char ch, unsigned count){ 2 unsigned int cnt = 0; 3 while(*(buf++) != ch && cnt <= count){cnt++;} 4 if(cnt > count) 5 return NULL; 6 else 7 return buf; 8 }
红色部分报错。
该错误为为ANSIC中认定的错误,是因为它坚持:进行算法操作的指针必须是确定知道其指向数据类型大小的。
但是GNU则不这么认定,它指定void * 的算法操作与char * 一致。
在实际的程序设计中,为迎合ANSI标准,并提高程序的可移植性,我们可以对void指针先进行强制类型转换为特定类型的指针。
则上述代码修改为:
1 void *memchr(const void *buf, char ch, unsigned count){ 2 unsigned int cnt = 0; 3 while(*((char *)buf++) != ch && cnt <= count){cnt++;} 4 if(cnt > count) 5 return NULL; 6 else 7 return buf; 8 }
使用测试程序测试:
1 int main(void) 2 { 3 char *s = "hello world"; 4 char *ptr = memchr(s,'w',10); 5 printf("%x %x %c",s,ptr,*ptr); 6 return 0; 7 }
输出结果为:
403000
403007
o
有错,理论上*ptr应该为w
循环条件上多加了1
最终的程序:
1 void *memchr(const void *buf, char ch, unsigned count){ 2 unsigned int cnt = 0; 3 while(*((char *)buf++) != ch && cnt <= count){cnt++;} 4 if(cnt > count) 5 return NULL; 6 else 7 return (char *)buf - 1; 8 }
microsoft visual C 中的memchr的实现为:
1 void * __cdecl memchr ( 2 const void * buf, 3 int chr, 4 size_t cnt 5 ) 6 { 7 while ( cnt && (*(unsigned char *)buf != (unsigned char)chr) ) { 8 buf = (unsigned char *)buf + 1; 9 cnt--; 10 } 11 12 return(cnt ? (void *)buf : NULL); 13 }
参考其代码仍有两点可以改进:
1.可将最后的if语句改为三元表达式的形式。
2.使用unsigned char保证能接受非常规的字符(如字符¥的ASCII码值在850 (Latin 1)为190),同时保证字符运算时结果的正确性(有符号数的运算结果会受符号位的影响,如0-(-128)=-128)。
完