C++面试八股文之如何实现strncpy函数
作者:二进制架构
某日二师兄参加XXX科技公司的C++工程师开发岗位第31面:
面试官:strcpy
函数使用过吧?
二师兄:用过。
面试官:这个函数有什么作用?
二师兄:主要用做字符串复制,将于字符从一个位置复制到另一个位置。
面试官:strncpy
函数也使用过吧,和strcpy
有何不同?
二师兄:strncpy
多了一个size_t
的参数,用于避免缓冲区溢出。
面试官:能否实现一个strncpy
函数?
二师兄:好的。
void strncpy(char *dest, char *src, size_t n) { for (size_t i = 0; i < n; i++) { *(dest + i) = *(src + i); } }
面试官:额。。如果strlen(src) < n
会发生什么?
二师兄:嗯。。那要做个判断。。
void strncpy(char *dest, char *src, size_t n) { size_t len = strlen(src) > n ? n : strlen(src); for (size_t i = 0; i < len; i++) { *(dest + i) = *(src + i); } }
面试官:如果strlen(dest) < n
呢?
二师兄:因为n
是程序员传入进来的,且无法知晓dest的长度,所以这个n
要程序员保证它的正确性。
面试官:有没有更简洁的写法?比如利用指针的自增?
二师兄:让我想想。。
void strncpy(char *dest, char *src, size_t n) { while(n-- && (*dest++ = *src++)); }
面试官:如果用户传入的src
是字符串常量,会发生什么?
二师兄:额。。。让我想想。。明白了,要在src
前加上const
修饰符:
void strncpy(char *dest, const char *src, size_t n) { while(n-- && (*dest++ = *src++)); }
面试官:有一些操作需要strcpy
嵌套strcpy
,如果要实现这个功能,需要做哪些修改?
二师兄:你说的是strncpy(strncpy(...)...)
这种操作吗?
面试官:是的。
二师兄:那么需要返回dest
地址:
char *strncpy(char *dest, const char *src, size_t n) { char *ret = dest; while (n-- && (*dest++ = *src++)); return ret; }
面试官:如果src
和dest
的内存地址有重叠,会发生什么?
二师兄:这要分为两种情况,第一种情况:dest < src < dest+n
:
二师兄:此时并不需要特殊的处理,拷贝完成后,整个字符串是这样的:
二师兄:虽然src
被覆写了,但是dest
的内容是正确的。
二师兄:第二种情况,src < dest <src+n
;
二师兄:如果直接拷贝,结果会变成这样:
二师兄:此时dest
的内容是错误的。所以我们需要对这种情况做特殊处理:
char *strncpy(char *dest, const char *src, size_t n) { char *ret = dest; size_t len = strlen(src) > n ? n :strlen(src); if(src < dest && dest < src + len) //需要从尾部开始拷贝 { const char* s = src + len - 1; char* d = dest + len - 1; while(len --) *d-- = *s--; return ret; } while (n-- && (*dest++ = *src++)); return ret; }
面试官:嗯。有没有什么办法对以上的代码做一些性能上的优化?
二师兄:可以使用SIMD(Single Instruction Multiple Data)
指令对strncpy
函数做一些优化。*dest++ = *src++
每次只能复制一个字节的内容,而SIMD
每次可以复制超过一个字节的内容,当数据量大的时候,效率会有明显的提升。
面试官:写过SIMD
相关的代码吗?
二师兄:只是听说过,没有用过。
面试官:好的,今天就到这里,请回去等通知吧。
什么是SIMD
?SIMD
真的能够提升效率吗?
SIMD
是一种常见的并行计算技术,一条指令可以同时处理多个数据,所以它可以减少指令的数量,从而提高处理速度。
在X86_64
架构下,SIMD
的指令集主要包括MMX
、SSE
、AVX
。
下面代码演示如果使用SIMD
技术加速大容量字符串的拷贝:
#include <emmintrin.h> void strncpy_simd(char *dest, const char *src, size_t n) { size_t len = strlen(src) > n ? n : strlen(src); __m128i *d = (__m128i *)dest; const __m128i *s = (const __m128i *)src; while (len >= sizeof(__m128i)) { _mm_storeu_si128(d++, _mm_loadu_si128(s++)); len -= sizeof(__m128i); } char *dc = (char *)d; const char *sc = (const char *)s; while (len--) { *dc++ = *sc++; } }
今天的面试到这里就结束了,感谢大家的耐心~
到此这篇关于C++面试八股文之如何实现strncpy函数的文章就介绍到这了,更多相关C++实现strncpy函数内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!