C++面試八股文之如何實(shí)現(xiàn)strncpy函數(shù)
某日二師兄參加XXX科技公司的C++工程師開發(fā)崗位第31面:
面試官:strcpy
函數(shù)使用過吧?
二師兄:用過。
面試官:這個(gè)函數(shù)有什么作用?
二師兄:主要用做字符串復(fù)制,將于字符從一個(gè)位置復(fù)制到另一個(gè)位置。
面試官:strncpy
函數(shù)也使用過吧,和strcpy
有何不同?
二師兄:strncpy
多了一個(gè)size_t
的參數(shù),用于避免緩沖區(qū)溢出。
面試官:能否實(shí)現(xiàn)一個(gè)strncpy
函數(shù)?
二師兄:好的。
void strncpy(char *dest, char *src, size_t n) { for (size_t i = 0; i < n; i++) { *(dest + i) = *(src + i); } }
面試官:額。。如果strlen(src) < n
會(huì)發(fā)生什么?
二師兄:嗯。。那要做個(gè)判斷。。
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
呢?
二師兄:因?yàn)?code>n是程序員傳入進(jìn)來的,且無法知曉dest的長(zhǎng)度,所以這個(gè)n
要程序員保證它的正確性。
面試官:有沒有更簡(jiǎn)潔的寫法?比如利用指針的自增?
二師兄:讓我想想。。
void strncpy(char *dest, char *src, size_t n) { while(n-- && (*dest++ = *src++)); }
面試官:如果用戶傳入的src
是字符串常量,會(huì)發(fā)生什么?
二師兄:額。。。讓我想想。。明白了,要在src
前加上const
修飾符:
void strncpy(char *dest, const char *src, size_t n) { while(n-- && (*dest++ = *src++)); }
面試官:有一些操作需要strcpy
嵌套strcpy
,如果要實(shí)現(xiàn)這個(gè)功能,需要做哪些修改?
二師兄:你說的是strncpy(strncpy(...)...)
這種操作嗎?
面試官:是的。
二師兄:那么需要返回dest
地址:
char *strncpy(char *dest, const char *src, size_t n) { char *ret = dest; while (n-- && (*dest++ = *src++)); return ret; }
面試官:如果src
和dest
的內(nèi)存地址有重疊,會(huì)發(fā)生什么?
二師兄:這要分為兩種情況,第一種情況:dest < src < dest+n
:
二師兄:此時(shí)并不需要特殊的處理,拷貝完成后,整個(gè)字符串是這樣的:
二師兄:雖然src
被覆寫了,但是dest
的內(nèi)容是正確的。
二師兄:第二種情況,src < dest <src+n
;
二師兄:如果直接拷貝,結(jié)果會(huì)變成這樣:
二師兄:此時(shí)dest
的內(nèi)容是錯(cuò)誤的。所以我們需要對(duì)這種情況做特殊處理:
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; }
面試官:嗯。有沒有什么辦法對(duì)以上的代碼做一些性能上的優(yōu)化?
二師兄:可以使用SIMD(Single Instruction Multiple Data)
指令對(duì)strncpy
函數(shù)做一些優(yōu)化。*dest++ = *src++
每次只能復(fù)制一個(gè)字節(jié)的內(nèi)容,而SIMD
每次可以復(fù)制超過一個(gè)字節(jié)的內(nèi)容,當(dāng)數(shù)據(jù)量大的時(shí)候,效率會(huì)有明顯的提升。
面試官:寫過SIMD
相關(guān)的代碼嗎?
二師兄:只是聽說過,沒有用過。
面試官:好的,今天就到這里,請(qǐng)回去等通知吧。
什么是SIMD
?SIMD
真的能夠提升效率嗎?
SIMD
是一種常見的并行計(jì)算技術(shù),一條指令可以同時(shí)處理多個(gè)數(shù)據(jù),所以它可以減少指令的數(shù)量,從而提高處理速度。
在X86_64
架構(gòu)下,SIMD
的指令集主要包括MMX
、SSE
、AVX
。
下面代碼演示如果使用SIMD
技術(shù)加速大容量字符串的拷貝:
#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++; } }
今天的面試到這里就結(jié)束了,感謝大家的耐心~
到此這篇關(guān)于C++面試八股文之如何實(shí)現(xiàn)strncpy函數(shù)的文章就介紹到這了,更多相關(guān)C++實(shí)現(xiàn)strncpy函數(shù)內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
C++ 自由存儲(chǔ)區(qū)是否等價(jià)于堆你知道嗎
自由存儲(chǔ)是C++中通過new與delete動(dòng)態(tài)分配和釋放對(duì)象的抽象概念,而堆(heap)是C語言和操作系統(tǒng)的術(shù)語,是操作系統(tǒng)維護(hù)的一塊動(dòng)態(tài)分配內(nèi)存2021-08-08C++分析如何用虛析構(gòu)與純虛析構(gòu)處理內(nèi)存泄漏
虛析構(gòu)和純虛析構(gòu)共性:可以解決父類指針釋放子類對(duì)象,都需要有具體的函數(shù)實(shí)現(xiàn);虛析構(gòu)和純虛析構(gòu)區(qū)別:如果是純虛析構(gòu),該類屬于抽象類,無法實(shí)例化對(duì)象2022-08-08Qt結(jié)合libqrencode生成二維碼的實(shí)現(xiàn)示例
本文主要介紹了Qt結(jié)合libqrencode生成二維碼的實(shí)現(xiàn)示例,文中通過示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2022-01-01C語言scandir函數(shù)獲取文件夾內(nèi)容的實(shí)現(xiàn)
scandir?函數(shù)用于列舉指定目錄下的文件列表,本文主要介紹了C語言scandir函數(shù)獲取文件夾內(nèi)容的實(shí)現(xiàn),具有一定的參考價(jià)值,感興趣的可以了解一下2024-03-03vc6.0中c語言控制臺(tái)程序中的定時(shí)技術(shù)(定時(shí)器)
這篇文章主要介紹了vc6.0中c語言控制臺(tái)程序中的定時(shí)技術(shù)(定時(shí)器),需要的朋友可以參考下2014-04-04