乐趣区

关于c++: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;
}

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

二师兄:这要分为两种状况,第一种状况: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 相干的代码吗?

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

面试官:好的,明天就到这里,请回去等告诉吧。

什么是 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++!(狗头)

退出移动版