网站seo关键词排名优化,wordpress 四亩,多语言网站建设应注意哪些事项,成都微信公众号外包Void与void*的区别
定义#xff1a;
Void#xff1a;空类型#xff0c;是数据类型的一种
Void*#xff1a;是指针类型#xff0c;是指针类型的一种#xff0c;可以匹配任何类型的指针#xff0c;类似于通配符
Void
说明#xff1a;void作为返回值类型使用#xf…Void与void*的区别
定义
Void空类型是数据类型的一种
Void*是指针类型是指针类型的一种可以匹配任何类型的指针类似于通配符
Void
说明void作为返回值类型使用表示没有返回值作为参数表示形参列表为空在调用函数时不能给实参
// 函数声明
void fun(void); // 等效于 void fun();
// 函数调用
fun();
Void*
说明
void*是一个指针类型但是该指针的数据类型是不明确的无法通过解引用获取内存中的数据因为void*不知道访问几个内存单元void*是一种数据类型可以作为函数返回值类型也可以作为形参类型void*类型的变量在使用之前必须强制类型转换
int *p (int*)malloc(4);
double *p2 (double*)malloc(8);举例
#include stdio.h
#include stdlib.h
// 函数定义
void* fun(void* p) // 指针函数返回值类型是指针的函数此时返回的是不明确类型需要外部强转
{
int *p;
// double *p;
// long *p;
// char *p;
return p;
}
// 函数调用
void main()
{
int *p;
void* a fun(p);// 这种接收方式实际上没有意义
printf(%p\n,a);// 可以正常打印打印出一个地址
*a 10;// 编译报错void*变量不能解引用访问数据
int *w (int*)a;
*w 10;// 编译和运行正常void*变量a在使用前已经强制类型转换了数据类型明确了访问的内存
单元明确了。
}说明
void*作为返回值类型这个函数可以返回任何类型char* int* double*的指针void*作为形参的类型这个函数在调用时可以给任意类型的指针
总结
void*类似于通配符不能对void*类型的变量解引用因为不明确内存单元的大小void*在间接访问解引用前要强制类型转换但不能太随意否则存和取的数据类型不一致
内存操作
我们对于内存的操作借助于string.h这个库提供的内存操作函数。
内存填充
头文件#includestring.h
函数原型void*memsetvoid*sint csize_t n;
函数功能填充s开始的堆内存前n个字节使得每个字节值为c
函数参数
void*s待操作内存的首地址int c填充的字节数据size_t n:被填充的字节数
返回值返回s
注意c常常设置为0用于动态内存初始化 /**
* 内存操作函数-memset
*/
#include stdio.h
#include stdlib.h
#include string.h
void test1()
{
// 在堆内存申请了一块存储空间
int *p (int*)malloc(4 * sizeof(int));
if(!p)
{
puts(内存分配失败);
return;// 后续代码不需要执行
}
// 给这块内存进行初始化操作填充
memset(p,0, 4 * sizeof(int));
printf(%d\n,*(p1));
// 内存使用完毕进行回收
free(p);
p NULL;
}
int main()
{
test1();
return 0;
}
内存拷贝
头文件#includestring.h
函数原型
void*memcpyvoid*destconst void*srcsize_t n;适合目标地址与源地址内存无重叠的情况void*memmovevoid*destconst void*srcsize_t n
函数功能拷贝src开始的堆内存空间前n个字节到dest对应的内存中
函数参数
void*dest目标内存的首地址void* src源内存首地址size_t n:被拷贝的字节数
返回值返回dest
注意内存申请了几个内存空间就访问几个内存空间否则数据不安全
注意memcpy与memmove一般情况下是一样的更建议使用memmove进行内存拷贝因为mememove函数是从自适应从后往前从前往后拷贝当我们被拷贝的内存和目的地的内存有重叠时数据不会出现拷贝错误而memecpy函数是从前往后拷贝当被拷贝的内存和目的地有重叠时数据会出现拷贝错误
/**
* 内存操作函数-memcpy|memmove
*/
#include stdio.h
#include stdlib.h
#include string.h
void test1()
{
// 申请内存
// int *p1 (int*)malloc(4 * sizeof(int));
// int *p2 (int*)malloc(6 * sizeof(int));
// 给p1,p2填充数据可以使用for循环..
// for(int i 0; i 4; i)
// p1[i] 10 i;
// memset(p2,0,6 * sizeof(int));
// 创建数组
int p1[4] {11,12,13,14};
int p2[6] {21,22,23,24,25,26};
// 将p1中的数据通过内存拷贝函数拷贝到p2
// memcpy(p22,p11,2*sizeof(int)) // int p2[6] {21,22,12,13,25,26}
memmove(p22,p11,2*sizeof(int));
// 测试输出数组
for(int i 0; i 4; i)
printf(%4d,p1[i]);
printf(\n);
for(int j 0; j 6; j)
printf(%4d,p2[j]);
printf(\n);
// 如果使用手动分配的指针一定要记得释放内存
// free(p1);
// free(p2);
// p1 NULL;
// p2 NULL;
}
int main()
{
test1();
return 0;
}内存比较
头文件#includestring.h
函数原型int memcmpvoid*dest,const void*src,size_t n
函数功能比较src和dest所代表的内存前n个字节数据
函数参数
void*dest目标内存首地址const void*src源内存首地址size_t n:比较的字节数
返回值
0数据相同0dest中的数据大于src目标大于源0dest中的数据小于src
注意n一般和srcdest的总容量一样如果不一样内存比较的结果就不确定
案例
/**
* 内存操作-memcmp
*/
#include stdio.h
#include stdlib.h
#include string.h
void test1()
{
// 申请内存
int *p1 (int*)malloc(3*sizeof(int));
int *p2 (int*)malloc(4*sizeof(int));
// int p1[4] {1,0,3,6};
// int p2[4] {1,2,3,4};
// int result memcmp(p1,p2,4*sizeof(int));
*p1 65;
*p2 70;
char *a (char*)p1;// 类型转换
char *b (char*)p2;
printf(%c,%c\n,*a,*b);
int result memcmp(a1,b1,1*sizeof(char));
printf(%d\n,result);
}
int main()
{
test1();
}内存查找
头文件#includestring.h
函数原型void *memrchr | *memchr(const void *s, int c, size_t n);
函数功能在s开始的堆内存空间前n个字节中查找字节数据c
函数参数
const void *s待操作内存首地址int c待查找的字节数据size_t n查找的字节数
返回值返回查找到的字节数据地址
注意如果内存中没有重复数据memchr和memrchr结果是一样的若果有重复数据memchr和memrchr结果就不一样
案例
/**
* 内存操作-memchr | memrchr
*/
#include stdio.h
#include stdlib.h
#include string.h
// 声明外部函数
extern void *memrchr(const void *s,int c,size_t n);
void test1()
{
// 申请内存
int *p (int*)malloc(4*sizeof(int));
if(!p)
{
puts(内存分配失败);
return;
}
// 给变量赋值
for(int i 0; i 4; i)
{
p[i] i * 2;
}
p[3] 4;
// 输出
for(int i 0; i 4; i)
{
printf(%d,,p[i]);
}
printf(\n);
// 内存查找 memchr
int *x (int*)memchr(p,4,4*sizeof(int));
printf(%p--%p--%d\n,x,p,*x);
// 内存查找 memrchr
int *y (int*)memrchr(p,4,4*sizeof(int));
printf(%p--%p--%d\n,y,p,*y);
// 回收内存
free(p);
p NULL;
}
int main()
{
test1();
}
本章小结
1. 指针就是地址。变量的指针就是变量的地址。指针变量就是地址变量。 指针是地址本身指针变量是用来存放地址的变量。
2. 指向 把谁的地址存放在指针变量中该指针变量就指向谁
3. 深入掌握对数组操作中怎样正确使用指针。
4. 有关指针变量的定义形式归纳比较见表8-4。
5. 指针运算小结 ① 指针变量加(减)一个整数 p、p--、pi、p-i、pi、p-i 等均使指针变量p加(减)一个整数。改变了指向的地址值。 ② 指针变量赋值 不要把一个整型数赋给指针变量 ③ 指针变量可以赋空值 pNULL 即不指向任何变量 ④ 两个指针变量可以相减 两个指向同一数组的指针变量可以相减得到两个指针之间元素的个数但相加无意义 ⑤ 两个指针变量比较 两个指向同一数组的指针变量可以比较指向前面元素的指针“小于”指向后面元素的指针变量