学逆向论坛

找回密码
立即注册

只需一步,快速开始

发新帖

489

积分

0

好友

60

主题
发表于 2025-2-11 11:45:10 | 查看: 156| 回复: 0
本帖最后由 jinchanchan 于 2025-2-11 11:52 编辑

某日二师兄参加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

C++面试八股文:如何实现一个strncpy函数?

C++面试八股文:如何实现一个strncpy函数?
二师兄:此时并不需要特殊的处理,拷贝完成后,整个字符串是这样的

C++面试八股文:如何实现一个strncpy函数?

C++面试八股文:如何实现一个strncpy函数?
二师兄:虽然src被覆写了,但是dest的内容是正确的。
二师兄:第二种情况,src < dest <src+n

C++面试八股文:如何实现一个strncpy函数?

C++面试八股文:如何实现一个strncpy函数?
二师兄:如果直接拷贝,结果会变成这样:

C++面试八股文:如何实现一个strncpy函数?

C++面试八股文:如何实现一个strncpy函数?
二师兄:此时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++;
    }
}
今天的面试到这里就结束了,感谢大家的耐心~

<顺便吆喝一句,民族企业大厂,前后端测试捞人,感兴趣的来!→https://jsj.top/f/o38ijj>

温馨提示:
1.如果您喜欢这篇帖子,请给作者点赞评分,点赞会增加帖子的热度,评分会给作者加学币。(评分不会扣掉您的积分,系统每天都会重置您的评分额度)。
2.回复帖子不仅是对作者的认可,还可以获得学币奖励,请尊重他人的劳动成果,拒绝做伸手党!
3.发广告、灌水回复等违规行为一经发现直接禁言,如果本帖内容涉嫌违规,请点击论坛底部的举报反馈按钮,也可以在【投诉建议】板块发帖举报。
已有 1 人评分学币 理由
pejoju2025 + 1 感谢您的热心分享,学逆向论坛有你更精彩!.

总评分: 学币 + 1   查看全部评分

小黑屋|手机版|站务邮箱|学逆向论坛 ( 粤ICP备2021023307号 )|网站地图

GMT+8, 2025-2-21 22:25 , Processed in 0.126569 second(s), 38 queries .

Powered by Discuz! X3.4

Copyright © 2001-2021, Tencent Cloud.

快速回复 返回顶部 返回列表