深入解析void*万能指针的奥秘
本文主要介绍了C语言中void指针和指针数组的使用方法。void指针作为通用指针类型,可以存储任意类型的地址,但在使用时需要进行强制类型转换。文章通过memcpy函数的实现示例展示了void指针的应用场景。指针数组则是指针元素的数组,常用于存储字符串地址,文章详细说明了其定义、初始化和传参方式。此外还介绍了数组指针与二维数组的关系,以及如何通过数组指针传递二维数组参数。这些指针技术为C语言提供了灵
十四、void* 万能指针
void可以做函数的返回值,
从来没有出现过void a;原因是void是空类型,编译器并不知道给a开辟多大的空间。
void* 可以做函数的返回值、函数的参数。
void* 作为函数的参数的时候,可以接收任意类型指针。
- void* 主要用来保存内存的地址。
- 其他任意类型的指针给void* 赋值或者参数传递,不需要额外的操作,直接赋值或传递参数。
- 当需要把void* 转换为其他类型指针的时候,需要强制类型转换后,才可以使用。因为void* 中只保留的地址,不知道如何对数据进行访问。如果没有转换,*p (解引用)、p+1(挪到下一个元素)都会失败,void没说开多大的空间,没有void 类型的变量。
- void* ,做函数的返回值,做函数的参数。
void指针典型的用法
void* my_memcpy(void* dst,void* src,int size) //size是src的总字节数
{
char* pdst=(char*)dst;
char* psrc=(char*)src;int i=0;
for(i=0;i<size;i++)
{
*pdst=*psrc;
pdst++;
psrc++;
}
return dst;
}#include <stdio.h> #include <stdlib.h> #include <string.h> void* my_memcpy(void* dst,void* src,int size) //size是src的总字节数 { char* pdst=(char*)dst; char* psrc=(char*)src; int i=0; for(i=0;i<size;i++) { *pdst=*psrc; pdst++; psrc++; } return dst; } int main() { double d1[5]={1.11,2.22,3.33,4.44,5.55}; double d2[5]={0}; my_memcpy(d2,d1,sizeof(d1)); //8*5=40 int i=0; for(i=0;i<5;i++) { printf("%lf\n",d2[i]); } return 0; }
十五、指针数组
指针数组的定义
类型* [ 常量表达式] = {NULL};指针不确定,先指到空,之后找到相应的位置。
指针数组,数组中存储的元素是指针类型
char* arg1[10]={NULL}; 常用,这里装了10个指针
int* arg2[10];
char* arg[5]={"hello","worlg","ok","fine","end"};
arg是一个数组,里面存储了5个地址
每个指针都存储了字符常量的地址,每个指针不能改变指向的内容,指针自己可以走,指针可以指向其他位置。
char str[100]={0};
arg[0]=str;
那么arg[0]和str这个字符数组进行了关联,
如果执行strcpy(arg[0],“hello“),那么相当于给str,写入“hello”,arg[0]中存储的是数组(str)的地址。
示例
#include <stdio.h>
#include <string.h>
int main()
{
char* arg[5]={"hello","world","ok","fine","end"};
int i=0;
for(i=0;i<5;i++)
{
printf("%d %s\n",i,arg[i]);
}
arg[0]="aaa"; //这里是赋值
for(i=0;i<5;i++)
{
printf("%d %s\n",i,arg[i]);
}
char str1[100]={0};
arg[0]=str1;
strcpy(arg[0],"bbb"); // 这里是函数的的调用,如果不开辟一个新空间,原来的“hello”是一个字符串常量,无法修改。
for(i=0;i<5;i++)
{
printf("%d %s\n",i,arg[i]);
}
char* p="hello";
char str2[100]={0};
p=str2;
strcpy(p,"ccc");
return 0;
}
#include <stdio.h>
int main()
{
char str[100]="how are you";
char* arg[3]={NULL};
char* tmp=str;
arg[0]=str;
int i=1;
while(*tmp && i<3)
{
if(' '==*tmp)
{
arg[i]=tmp+1;
*tmp='\0';
i++;
}
tmp++;
}
for(i=0;i<3;i++)
{
printf("%d %s\n",i,arg[i]);
}
return 0;
}
指针数组的传参
char* pstr[ ] 和 char** pstr 表达的含义是一样的
#include <stdio.h>
void show1(char* pstr[],int size)
{
int i=0;
for(i=0;i<size;i++)
{
printf("%d %s\n",i,pstr[i]);
}
}
void show2(char** pstr,int size)
{
int i=0;
for(i=0;i<size;i++)
{
//printf("%d %s\n",i,pstr[i]);
printf("%d %s\n",i,*(pstr+i));
}
}
int main()
{
char* str1[]={"hello","aaa","bbb"};
show1(str1,3);
show2(str1,3);
return 0;
}
十六、数组指针
应用:函数需要传递二维数组的时候,会使用数组指针,在被调函数中,数组的内容可读可写
1、数组指针
主语是指针,指针往哪里指?指向谁?
数组指针本质是指针,指向二维数组当中的某一行,一般来说是起始位置,存储的是一个数组的地址,一般和二维数组搭配使用。
&a(取地址a) int(*) [5] 数组指针,获得整个一维数组
int a[5]={1,2,3,4,5};
- 对一维数组进行取地址 & 操作:&a[0],&a,a 地址不变。a是变量,&a不能看做二级指针,&a叫做数组指针,表示的是整个一维数组,&a+1 偏移量:5*sizeof(int)=20
- 对数组指针执行解引用 * 操作,&a地址值不变(都是&a[0]的地址) *&a == a;表示的是数组中的一个变量的地址 sizeof(int)=4
int * 和 int[ ]的区别
sizeof(*int)==8;
sizeof(int[ ])=sizeof(int) * 元素的个数;
&取地址
- int*-----> int** 二级指针
-
int[]---> int(*)[3] 数组指针
#include <stdio.h>
int main()
{
int a[5]={1,2,3,4,5};
printf("&a[0] %p\n",&a[0]);
printf("&a[1] %p\n",&a[1]);
printf("&a[2] %p\n",&a[2]);
printf("a %p \n",a); // int* = int[]
printf("a+1 %p \n",a+1);
printf("a+3 %p \n",a+3);
printf("a[0] %d \n",a[0]);
printf("a[1] %d \n",a[1]);
printf("a[3] %d \n",a[3]);
// &a int (*)[5] 数组指针 ,获得整个一维数组
printf("&a %p\n",&a); //&a = int(*)[5]
printf("&a+1 %p\n",&a+1);
int (*p)[5]=&a;
printf(" *&a %p \n",*&a);
printf(" *&(a+1)%p \n", *(&a+1));
printf("a[0] %d\n",p[0][0]);
printf("a[0] %d\n",*((*(p+0))+0));
return 0;
}
2、二维数组和数组指针
二维数组的传参
#include <stdio.h>
void show(int (*p)[2],int line ,int col )
{
int i = 0 ;
int j = 0 ;
for(j=0;j<line;j++)
{
for(i=0;i<col;i++)
{
// printf("%d\n",p[j][i]);
printf("%d\n",*(*(p+j)+i));
}
}
}
int main()
{
int a[3][2]={1,2,3,4,5,6};
show(a,3,2);
return 0;
}
更多推荐



所有评论(0)