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++;
}
}
今天的面试到这里就结束了,感谢大家的耐心~
关注我,带你21天“精通”C++!(狗头)
C++面试八股文:如何实现一个strncpy函数?的更多相关文章
- 《面试八股文》之kafka21卷
微信公众号:moon聊技术 关注选择" 星标 ", 重磅干货,第一 时间送达! [如果你觉得文章对你有帮助,欢迎关注,在看,点赞,转发] 大家好,我是moon,最新一篇面试八股文系 ...
- strncpy函数使用
strncpy()函数原型:extern char *strncpy(char *dest, char *src, int n); 用法:#include <string.h> ...
- strcpy函数和strncpy函数的区别
strcpy函数和strncpy函数的原型介绍在我的另一篇文章中介绍了,见strcpy,strncpy,strlen等函数原型 strcpy:字串复制 原型:char *strcpy(char *de ...
- strlen函数,strcat函数,strcpy函数,strncpy函数,strcmp函数
strcpy函数: char *strcpy(char *Dest , const char *Src) { assert((Dest != NULL) && (Src != NULL ...
- 《面试八股文》之 Redis 16卷
微信公众号:moon聊技术 关注选择" 星标 ", 重磅干货,第一 时间送达! [如果你觉得文章对你有帮助,欢迎关注,在看,点赞,转发] 大家好,我是 moon. redis 作为 ...
- 《面试八股文》之 JVM 20卷
微信公众号:moon聊技术 关注选择" 星标 ", 重磅干货,第一 时间送达! [如果你觉得文章对你有帮助,欢迎关注,在看,点赞,转发] 大家好,我是 moon. <面试八股 ...
- 请写一个php函数,可以接受任意数量的参数
请写一个php函数,可以接受任意数量的参数 这是一道面试题.怎么写这个函数呢? function fun(......) { } ----------------------------------- ...
- 在String()构造器不存在的情况下自定义一个MyString()函数,实现如下内建String()方法和属性:
在String()构造器不存在的情况下自定义一个MyString()函数,实现如下内建String()方法和属性: var s = new MyString("hello"); s ...
- 如何实现一个malloc函数
一.概述 1.malloc简介 函数所在头文件:<stdlib.h> 函数原型是:void *malloc (size_t n) 函数功能:在内存的动态存储区中分配一个长度为size的连续 ...
- 研究不定数量参数的函数并实现一个printf函数
一.前提知识 1.如何传递参数(主函数) a.函数的参数是通过栈传递,而且是从右到左依次入栈 b.即使是char型变量,在传递参数时,也是占用两个字节,因为push操作是两个字节为单位的. c.sho ...
随机推荐
- 从ajax到跨域引发的相关面试题总结
转载请注明出处: 1.ajax异步和同步的区别 Ajax是一种基于JavaScript语言和XMLHttpRequest对象的异步数据传输技术,通过它可以使不用刷新整个页面的情况下,对页面进行部分更新 ...
- 在Vue中使用键盘事件,回调函数被执行两次
暂时先不考虑v-for的key,查看下面的代码 <template> <div> <form @submit.prevent="addTask"> ...
- Docker构建镜像踩坑日记
从Github上拉取python项目后,运行dockerfile构建镜像失败,一步步查找原因 主要原因就是国内下载各种依赖超时,以下提供pip.apt.pipenv镜像解决方案 pip更换国内镜像 这 ...
- Linux云计算运维工程师day29软件安装
1. diff(文本比较) [root@guosaike ~]# cp /etc/passwd{,.ori}备份 [root@guosaike ~]# diff /etc/passwd{,.ori} ...
- VMware虚拟机---Ubuntu无法连接网络该怎么解决?
在学习使用Linux系统时,由于多数同学们的PC上多是Windows系统,故会选择使用VMware创建一个虚拟机来安装Linux系统进行学习. 安装完成之后,在使用时总是会遇到各种各样的问题.本片随笔 ...
- 命令行编译和执行java代码
虽然现在IDE很强大又很智能,但是平常随意写点练手的代码的时候,直接在命令行中使用vim和java命令更为方便快捷,可以做到无鼠标纯键盘的操作. 首先保证将java相关指令添加到了环境变量中: 1.编 ...
- Prism Sample 17-BasicRegionNavigation
本例是基础的导航应用 在窗口中布局了2个按钮,一个区域 <DockPanel LastChildFill="True"> <StackPanel Orientat ...
- Prism Sample 7 Modules LoadManual
这种模块是手动载入的,需要的时候手动加载. 在app.xaml.cs中注册为按需加载,代码 protected override void ConfigureModuleCatalog(IModule ...
- ai问答:使用 Vue3 组合式API 和 TS 封装 echarts 折线图
使用这个组件时,只需要传入合适的chartData数组,就可以渲染一个折线图,并且响应数据变化. <template> <div ref="chart" styl ...
- Oracle 定时任务job实际应用
目录 一.Oracle定时任务简介 二.dbms_job涉及到的知识点 三.初始化相关参数job_queue_processes 四.实际创建一个定时任务(一分钟执行一次),实现定时一分钟往表中插入数 ...