【函数重现】- strncpy 函数

函数重现系列导航


1. 函数简介

strncpy 函数为 C 库函数之一,用于字符串的拷贝。

  • 原型:char* strncpy(char* dest, const char* src, size_t num);
  • 所属头文件:<string.h>
  • 功能:将 src 指向的字符串的前 num 个字节拷贝到 dest 指向的内存空间,当 num 大于 src 所指向的字符串长度时,多余部分字符将由 \0 填充。
  • 返回:指向目标字符串的指针。

2. 函数说明

  • 既然为 strncpy 函数的重现,那么所重现的 strncpy 函数的基本功能、调用方法应与原库函数保持一致。
  • 在确保 dest 所指向的有效内存空间足够大的情况下,strncyp 的推荐用法为 strncyp(buf, p, strlen(p) + 1);,使用 strlen(p) + 1 作为 num 保证了拷贝完后 dest 指向的字符串以 \0 结尾。
  • strncpy 函数支持内存覆盖,且能正确地完成内存覆盖,即能保证目标字符串数据的完整性。当可能发生内存覆盖(源字符串在目标字符串之前)时,应先定位到源字符串与目标字符串的第 num 个字符处,从后向前进行字符串的拷贝。为了提高拷贝效率,可以按位宽进行拷贝后再按字符拷贝。
  • 函数返回值为目标字符串是为了让函数能够支持链式表达式,例如 strlen(strncpy(..))printf("%s\n",strncpy(..)) 等。

3. 函数重现:

char* strncpy(char* dest, const char* src, size_t num)
{
	// 如果两指针指向相同的内存地址,则直接返回即可
	if (dest == src)
	{
	    return dest;
	}
	
	int src_len = 0;
	const char* psrc = src; 
	while (*psrc++ != '\0')
	{
		src_len++;
	}
	
	// 计算出实际需要拷贝的字节数
	const int new_num = num > src_len? src_len : num;
	
    // 计算出以位宽为最小单位的个数以及剩余部分的字节数
	int word_num = new_num / sizeof(size_t);
	int byte_slice = new_num % sizeof(size_t);
    
    if (src < dest)
	{		
		char* bdest = (char*)((char*)dest + new_num - 1);
		const char* bsrc = (char*)((char*)src + new_num - 1);
		
		// 按字节从后向前拷贝
		while (byte_slice--)
		{
			*bdest-- = *bsrc--;
		}
        
        size_t* wdest = (size_t*)((size_t*)dest + word_num - 1);
		const size_t* wsrc = (size_t*)((size_t*)src + word_num - 1);
		
		// 按位宽从后向前拷贝
		while (word_num--)
		{
			*wdest-- = *wsrc--;
		}
	}
	else
	{
		size_t* wdest = (size_t*)dest;
		const size_t* wsrc = (size_t*)src;
		
		char* bdest = (char*)((size_t*)dest + word_num);
		const char* bsrc = (char*)((size_t*)src + word_num);
		
		// 按位宽从前向后拷贝
		while (word_num--)
		{
			*wdest++ = *wsrc++;
		}	

		// 按字节从前向后拷贝
		while (byte_slice--)
		{
			*bdest++ = *bsrc++;
		}		
	}	
	
	if (num > src_len)
	{
		// 计算出拷贝长度大于源字符串长度的字节数,并尽量按位宽为单位进行拷贝
		int word_surplus = (num - src_len) / sizeof(size_t);
		int byte_surplus = (num - src_len) % sizeof(size_t);
		
		char* bdest = dest + src_len;
		while (byte_surplus-- > 0)
		{
			*bdest++ = '\0';
		}
		
		size_t* wdest = (size_t*)bdest;
		while (word_surplus-- > 0)
		{
			*wdest++ = 0;
		}
	}
		
	return dest;
}
发布了60 篇原创文章 · 获赞 36 · 访问量 5921

猜你喜欢

转载自blog.csdn.net/qq_35692077/article/details/102991905
今日推荐