目录
1、字符串遍历
(1)for循环遍历
char arr[20] = "abcdefghijklmn";
int n = strlen(arr);
for (int i = 0; i < n-1; i++)
{
printf("%c", arr[i]);
}
printf("\n");
(2)指针遍历
此处p++不能放在while循环中,因为后置++,会导致第一次打印时从第二个字符开始打印 ;
若字符串以字符数组构成,char arr1[4]={'a','b','c','\0'};用指针遍历,字符数组末尾必须添加'\0',否则指针会向外访问变成野指针;
char* p = arr;
while (*p)
{
printf("%c", *p++);
}
printf("\n");
2、memcpy 不重叠内存拷贝
函数解释:void* memcpy(void* destination, void* sorse, size_t num);将num字节的值,从源指向的位置直接复制到目标指向的内存空间;memcpy不关心内容,即会拷贝'\0';memcpy用来处理不重叠的内存拷贝;
模拟实现思路
1、从源src指向的位置拷贝任意类型的内容到dest指向的内存空间中,最后返回目的地空间;所以这里不知道会传递什么类型的数组的地址,参数设置为void*类型;2、进入函数内部,对源指针解引用赋值给解引用目的地指针;但此处不能对void*类型的指针直接解引用和进行指针与运算,所以需要对指针类型强转;3、考虑到复制的num字节数可能极小,可能为奇数,所以指针类型强转为char*最合适,力度最小最精细;
模拟实现注意点
1、强转在语句中是临时的,所以不能在强转语句后 后置++,强转完成后++时强转已经失效;2、比如*((char*)dest); dest++;此时强转已失效,dest为void*类型,void*类型指针不能进行指针运算++;3、修改代码为dest=(char*)dest+1;4、此时整形6在内存中存储时,06 00 00 00,所以此时访问21个字节,有效访问到06;
#include<stdio.h>
#include<string.h>
void* my_memcpy(void* dest, const void* src, size_t num)
{
void* ret=dest;
while (num--)
{
*(char*)dest = *(char*)src;
dest = (char*)dest + 1;
src = (char*)src + 1;
//或者 *((char*)dest)++ = *((char*)src)++;
}
return ret;;
}
int main()
{
int arr1[10] = { 1,2,3,4,5,6,7,8,9,0 };
int arr2[15] = { 1,1,1,1,1,1,1,1,1,1,1,1,1,1,'\0'};
my_memcpy(arr2, arr1, 21);
//for (int i = 0; i < 15; i++)
//{
// printf("%d ", arr2[i]);
//}
int* p = arr2;
while (*p)
{
printf("%d ", *p);
p++;
}
return 0;
}
(重叠拷贝)
int arr[10] = { 1,2,3,4,5,6,7,8,9,0 };若想将{ 1,2,3,4,5 }拷贝到{ 3,4,5,6,7 }处,此时内存重叠;将1拷贝到3处,3即被覆盖,无法实现拷贝;
但在有的编辑器上,memcpy可实现重叠拷贝,即memmove的功能;
3、memmove 重叠内存拷贝
void* memmove(void* dest, const void* src, size_t num);
memmove(100分)函数功能同memcpy(60分)一致,但比memcpy更强大,能拷贝重叠的内存;
模拟实现
#include<stdio.h>
#include<assert.h>
void* my_memmove(void* dest, const void* src, size_t num)
{
assert(dest && src);
void* ret = dest;
if (dest < src) //前->后
{
while (num--)
{
*(((char*)dest)++) = *(((char*)src)++);
}
}
else //后->前
{
while (num--)
{
*(((char*)dest) + num) = *(((char*)src) + num);
//此时num已减一,指针跳过了num-1个字节,指向了第num个字节
}
}
return ret;
}
int main()
{
int arr[10] = { 1,2,3,4,5, 6,7,8,9,0 };
my_memmove(arr + 2, arr, 20);
for (int i = 0; i < 10; i++)
{
printf("%d ", arr[i]);
}
return 0;
}
模拟实现注意点
1、首先模拟思路是:根据源与目的指针的位置,分为两种不同的拷贝方式;2、dest<src,源指针在目的指针后,若重叠,则重叠部分在源指针前半部分,先拷贝重叠部分,源从前往后拷贝;拷贝时,强转为字符指针,字符指针+1跳过一个字符即一个字节,所以可用num--逐个字节拷贝;注意强转的临时性;2、src<dest,重叠在源后半部分,从后往前拷贝;指针跳过num-1个字节,指向第num个字节,此时倒着拷贝找到最后一个字节是关键;3、注意num--循环num次,--num循环num-1次;4、memcpy库函数在vs编译器上可以实现重叠拷贝,但不代表其他编译器上的效果,重叠拷贝用memmove最适合;5、if else是条件语句,函数只会进入一种情况,所以可用同一num,不会互相影响;
4、memcmp 内存比较
int memcmp(void* ptr1, void* ptr2, size_t num);
比较ptr1和ptr2所指向内存的前num个字节的内容;大于返回大于1的值,小于返回小于1的值,等于返回0;
函数使用举例:比较两数组首元素地址起的 前9个字节;
5、memset 内存块填充
void* memset( void* ptr, int value, size_t num );
将ptr所指向的内存空间的前num个字节的内容修改为value值;即逐字节修改,不可逐元素修改;
使用举例1:将arr1数组,从首元素起,前8个字节的值,修改为1
函数使用举例2:将arr2数组,从第二个元素地址起,前4个字节的值,修改为n