首页 > 编程语言 >C++面试八股文:如何实现一个strncpy函数?

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

时间:2023-07-03 22:22:26浏览次数:32  
标签:src 面试官 八股文 dest C++ char 师兄 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;
}

面试官:如果srcdest的内存地址有重叠,会发生什么?

二师兄:这要分为两种情况,第一种情况:dest < src < dest+n

file

二师兄:此时并不需要特殊的处理,拷贝完成后,整个字符串是这样的:

file

二师兄:虽然src被覆写了,但是dest的内容是正确的。

二师兄:第二种情况,src < dest <src+n;

file

二师兄:如果直接拷贝,结果会变成这样:

file

二师兄:此时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相关的代码吗?

二师兄:只是听说过,没有用过。

面试官:好的,今天就到这里,请回去等通知吧。

什么是SIMDSIMD真的能够提升效率吗?

SIMD是一种常见的并行计算技术,一条指令可以同时处理多个数据,所以它可以减少指令的数量,从而提高处理速度。

X86_64架构下,SIMD的指令集主要包括MMXSSEAVX

下面代码演示如果使用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++!(狗头)

标签:src,面试官,八股文,dest,C++,char,师兄,strncpy
From: https://www.cnblogs.com/binarch/p/17524299.html

相关文章

  • 41.C++中有几种类型的new
    41.C++中有几种类型的new在C++中,new有三种典型的使用方法:plainnew,nothrownew和placementnew(1)plainnew言下之意就是普通的new,就是我们常用的new,在C++中定义如下:void*operatornew(std::size_tsize)throw(std::bad_alloc){void*ptr=std::malloc(size);......
  • 24.C++中const和static的作用
    static●不考虑类的情况○隐藏。所有不加static的全局变量和函数具有全局可见性,可以在其他文件中使用,加了之后只能在该文件所在的编译模块中使用○默认初始化为0,包括未初始化的全局静态变量与局部静态变量,都存在全局未初始化区○静态变量在函数内定义,始终存在,且只进行一次初始......
  • 25.C++的顶层const和底层const
    任意常量对象为顶层const,包括常量指针;指向常量的指针和声明const的引用都为底层const  顶层const(top-levelconst)表示指针本身是个常量int*constptr=&m;  此时指针不可以发生改变,但是指针所指向的对象值是可以改变的  底层const(low-levelconst)表示指针所指的对象是常量......
  • 32.C和C++的类型安全
    什么是类型安全?类型安全很大程度上可以等价于内存安全,类型安全的代码不会试图访问自己没被授权的内存区域。“类型安全”常被用来形容编程语言,其根据在于该门编程语言是否提供保障类型安全的机制;有的时候也用“类型安全”形容某个程序,判别的标准在于该程序是否隐含类型错误。类......
  • 34.C++有哪几种的构造函数
    34.C++有哪几种的构造函数C++中的构造函数可以分为4类:默认构造函数:在没有显式定义构造函数时,C++会自动生成一个默认构造函数,该函数没有参数,不执行任何操作。初始化构造函数(有参数)拷贝构造函数:当使用现有对象初始化新对象时,拷贝构造函数被调用。它的语法是在函数声明时使用一......
  • 33.C++中的重载、重写(覆盖)和隐藏的区别
    (1)重载(overload)  重载是指在同一范围定义中的同名成员函数才存在重载关系。主要特点是函数名相同,参数类型和数目有所不同,不能出现参数个数和类型均相同,仅仅依靠返回值不同来区分的函数。重载和函数成员是否是虚函数无关。举个例子:classA{...virtualintfun();......
  • 【C++】关于常引用的问题 #什么是权限放大?权限放小?隐式或强制转换居然还有这一步?...#
    前言引用在c++中的使用非常常见,可以说是很重要的,引用的常引用相关的问题让很多人稍不留神就出错了,这里我们就来谈谈常引用的问题。关于权限关于权限有权限缩小和权限放大的问题,比如一个文件,当初它只有读的权限,而现在你给它再加个写的权限,这就是权限放大;又或当初它读,写的权限......
  • 11.既然有了malloc-free,C++中为什么还需要new-delete呢?直接用malloc-free不好吗?
    malloc/free和new/delete都是用来申请内存和回收内存的。在对非基本数据类型的对象使用的时候,对象创建的时候还需要执行构造函数,销毁的时候要执行析构函数。而malloc/free是库函数,是已经编译的代码,所以不能把构造函数和析构函数的功能强加给malloc/free,所以new/delete是必不可少......
  • C++学习笔记
    类型兼容不同类型的数据在一定条件下可以进行转换,比如intn='a',是将字符'a'赋值给整型变量n,在赋值过程中发生了隐式类型转换,字符类型的数据转换为整型数据。这种现象称为类型转换,也称为类型兼容。继承与派生继承方式public继承private继承protect继承类型兼容在C++中,基类与派生......
  • C++ 宏定义
    看到一段C++代码,大致是说如果如果定义了RUN_ALL_TESTS就执行下面的代码,遂研究了一下。#ifdefined(RUN_ALL_TESTS)//somecodehere#endif首先RUN_ALL_TESTS是定义的宏:#defineRUN_ALL_TESTS//空字符串#defineRUN_ALL_TESTS1//赋值为1#ifdefined......