1、指针强化1
1指针是一种数据类型
1 指针变量也是一种变量,占有内存空间,用来保存内存地址
测试指针变量占有内存空间大小。
2 *p 操作内存
int main()
{
int a=10;
int *p=NULL;
//指针指向谁,就把谁的地址赋值给指针
p=&a;
//通过*可以找到指针指向的内存区域,操作的是内存
*p=20;
printf("p=%d,&a=%d\n",p,&a);
printf("*p=%d,a=%d\n",*p,a);
//*在右侧,是取内存的值,是读
//*在左侧,是给内存的赋值,是写
int b=*p;
printf("b=%d\n",b);
return 0;
}
运行结果:
2、指针变量和它指向的内存块是两个不同的概念
int main()
{
char *p=NULL;
char buf[]="abcd";
printf("p1=%d\n",p);
//改变指针变量的值,也就是p的值,也就是地址的值
p=buf;
printf("p2=%d\n",p);
//指针变量和指针指向是两个不同的概念
p=p+1;
printf("p3=%d\n",p);
printf("buf=%s\n",buf);
printf("*p=%c\n",*p);//这里是打印一个字符,用的是%c
//改变指针指向的内存,并不影响指针的值也就是地址的值
buf[1]=‘1‘;
printf("p4=%d\n",p);
printf("buf1=%s\n",buf);
//给*p 赋值 *p=‘a‘; 不会改变指针变量的值
//只会改变所指的内存块的值
*p=‘z‘;
printf("p5=%d\n",p);
printf("buf2=%s\n",buf);
return 0;
}
运行结果:
3、写内存是要确保内存可写
int main()
{
//内存常量区,不可修改,修改后报错
char *buf="abcdf";
//buf[2]=‘1‘;//error
//这个是用数组复制到栈区,可以修改数组
char buf2[]="abcdef";
buf2[2]=‘3‘;
printf("%s\n",buf2);
//指针是一种数据类型,是指它指向的内存空间的数据类型
//p++是指针的步长,不同的数据类型指针步长不同,根据内存空间的数据类型确定
int a;
int *p=&a;
printf("p=%d\n",p);
p=p+1;
printf("p+1=%d\n",p);
char c;
char *q=&a;
printf("q=%d\n",q);
q=q+1;
printf("q+1=%d\n",q);
double d;
double *k=&a;
printf("k=%d\n",k);
k=k+1;
printf("k+1=%d\n",k);
//不允许向 NULL 和未知非法地址拷贝内存
char *p1=NULL;
//给p1指向的内存区域赋值
//strcpy(p1,"aaav");//error
char buf3[100];
p1=buf3;
strcpy(p1,"aaav");//ok
printf("p1=%s\n",p1);
return 0;
}
运行结果:
4不断的改变指针变量
int main()
{
char buf[100]="abcdef";
char *p;
//不断的给指针变量赋值,就是不断的改变指针变量
p=&buf[0];//给指针变量赋值
printf("p1=%d,p1=%c\n",p,*p);
p=&buf[1];//给指针变量赋值
printf("p2=%d,p2=%c\n",p,*p);
char *q=NULL;
q=(char *)malloc(100);
if(q==NULL)
{
return -1;//分配内存失败
}
printf("-------------------\n");
for (int i=0;i<strlen(buf);i++) {
p=&buf[i];//给指针变量赋值
printf("p3=%d,p3=%c\n",p,*p);
}
printf("-------------------\n");
//不断的改变p本身变量,跟p指向的内存块无关
char *p1=NULL;
p1 = (char *)malloc(100);
strcpy(p1, "1434534633432311");
for (int i=0; i<10; i++){
p = p1+i;
printf("%c ", *p);
}
return 0;
}
运行结果:
2、指针强化2
1间接赋值(*p)
int main()
{
//指针指向谁就是把谁的地址赋值给指针
int a=10;
int *p;
//建立关系
p=&a;
//通过*操作内存
*p=20;
printf("p=%d,a=%d\n",*p,a);
//通过指针间接赋值
// 1两个变量
// 2建立关系
// 3通过*操作内存,进行修改
return 0;
}
```运行结果:
2间接赋值(*p)是指针存在的最大意义
int get_value()
{
int a=10;
return a;
}
void get_value1(int a)
{
a=20;
}
void get_value2(int *p)
{
*p=33;
}
void get_value3(int *a1,int *a2,int *a3)
{
*a1=12;
*a2=13;
*a3=14;
}
int main()
{
//函数返回值
int a=get_value();
printf("a=%d\n",a);
//实参函数传递
get_value1(a);
printf("a=%d\n",a);
//如果想通过形参改变实参的内容,必须是地址传递
get_value2(&a);
printf("a=%d\n",a);
//那return 也可以获得值得改变,为什么还用指针那
//return只能返回一个值,那如是需要返回多个值怎么办
int a1,a2,a3;
get_value3(&a1,&a2,&a3);
printf("a1=%d a2=%d a3=%d\n",a1,a2,a3);
return 0;
}
运行结果:
3二级指针间接赋值
void get_str1(int *p)
{
p=0xccdd;
printf("get_str1:p=%p\n",p);//get_str1:p=0000CCDD
}
void get_str2(int **p)
{
*p=0xdddd;
}
int main()
{
int *p=0xaabb;//这里是直接给p附一个值
printf("p=%p\n",p);//p=0000AABB通过%p打印地址
get_str1(p);//是值传递,没有&都是值传递,并不改变
printf("main_get_str1:p=%p\n",p);//p=0000AABB
get_str2(&p);//是地址传递
//地址传递,一个*地址传递,用两个*来接,由于是地址传递,指针指向谁就把谁的地址传递给指针,所以get_str2()中的p就指向了主函数中的p,在get_str2()中修改*p就是修改P指向的内存区域,所以能够修改p的地址。
printf("main_get_str2:p=%p\n",p);//main_get_str2:p=0000DDDD
return 0;
}
运行结果:
3、指针强化3
理解指针必须和内存四区概念相结合
void fun(char *p)
{
//给p指向的内存区域拷贝内容
strcpy(p,"abcdefg");
}
void fun1(char *p)
{
if(p==NULL)//判断是否为空
{
return;
}
//给p指向的内存区域拷贝内容
strcpy(p,"abcdefg");
}
void fun2(char **p,int *len)
{
if(p==NULL)
{
return;
}
char *temp = (char *)malloc(100);
if(temp==NULL)
{
return;
}
strcpy(temp,"abcdefgh");
*p=temp;
*len=strlen(temp);
}
int main()
{
//输入,主调函数分配内存
char buf[100]={0};
fun(buf);
printf("buf=%s\n",buf);//buf=abcdefg
char *p1=NULL;
fun1(p1);//注意不能给NULL指针拷贝内容
//输出,被调用函数分配内容,地址传递
char *p=NULL;
int len=0;
fun2(&p,&len);
if(p!=NULL)
{
printf("p=%s len=%d\n",p,len);
}
return 0;
}
运行结果:
输出部分的四区图如下:
原文地址:https://blog.51cto.com/14165014/2453325
时间: 2024-10-17 20:14:40