C指针基础
1.指针是什么
指针就是地址,一个变量的地址就称为这个变量的指针
2.指针变量
1如何定义指针变量
类型名 *指针变量;
int*point_1,*point2; *号表示该变量的类型是指针型变量
定义指针变量必须指定数据的基类型,只有这样才能按照存储单元的长度和数据的存储形式正确的去除该数据。(涉及到指针的移动问题)
2引用指针变量:int *p=&a;
Printf(“%d\n”,*a);//输出a的值
Printf(“%o\n”,a);//输出a的地址
3指针变量作为函数参数
#include <stdio.h>
void swap(int *pa,int *pb)
{
int *temp;
temp=pa;
pa=pb;
pb=temp;
}
int main(void)
{
int a,b;
int *pa=&a,*pb=&b;
printf("plese input a and b:");
scanf("%d%d",&a,&b);
swap(pa,pb);
printf("a=%d,b=%d\n",*pa,*pb);
return 0;
}
3.通过指针变量引用数组
通过指针引用一维数组:
int a[10],*p;
p=a; //或者p=&a[0];
指针引用一维数组的运算:
P++,p--,++p,--p,p+1,p-1
#include<stdio.h>
intmain(void)
{
int a[10],*p;
p=a;
/*
for(int i=0;i<10;i++)
*(p+i)=i+1;
for(i=0;i<10;i++)
printf("%d ",*p++);
*/ //指针法
for(int i=0;i<10;i++)
a[i]=i+1;
for(i=0;i<10;i++)
prin a[i][j] *(*(a+i)+j)
tf("%d ",a[i]);
//下标法
printf("\n");
return 0;
}
指针法和下标法的比较:
C语言编译系统是将a[i]转换为*(a+i)处理的,因此下标法每次都需要转换下标,所以指针法执行效率更高
用数组名作为函数参数
记得在传递参数时传递数组元素的个数,可以传递数组名,也可以是传递数组指针名
通过指针引用二维数组
二维数组的元素地址:
int a[3][4];
a:a代表二位数组的首元素地址(二维数组由3个一维数组,每个一维数组有4个元素),因此a+1是序号为1的行的地址
a[i][j] *(*(a+i)+j)
&a[i][j] *(a+i)+j *a 0行0列地址
指向二维数组元素的指针变量:
1指向数组元素的指针变量
#include<stdio.h>
intmain(void)
{
int a[2][3]={1,2,3,4,5,6},*p;
for(p=*a;p<*a+6;p++)
{
if((p-*a)%3==0)
printf("\n");
printf("%d ",*p);
}
return 0;
}
2指向由m个元素组成的一维数组的指针变量
inta[2][3];
int(*p)[3]; p指向一个由3个元素组成的一维数组
p=a;
#include<stdio.h>
intmain(void)
{
int a[2][3]={1,2,3,4,5,6};
int (*p)[3];
p=a;
int i,j;
for(i=0;i<2;i++)
for(j=0;j<3;j++)
{
printf("%d",*(*(p+i)+j));
if(j==2)
printf("\n");
}
return 0;
}
要理解a ,a[0]的区别,下面这个例子可以看出来:
#include<stdio.h>
intmain(void)
{
int a[4]={1,2,3,4};
int (*p)[4];
p=&a;
printf("%d\n",(*p)[3]);
return 0;
}
如果将p=&a;改为p=a;
那么表示p指向的是a[0],*p为1,这和p的定义不符合,p不是指向一个整数,而是指向一个一维数组,一次编译错误
3.用指向数组的指针作为函数参数。
int a[3][4]; void f(int (*p)[4],int n);
f(*a,2);
4.通过指针引用字符串
字符串引用的方式:
C语言对字符串常量的处理是字符数组处理的,在内存中开辟一个字符数组用来存放该字符串常量(默认在字符数组末尾放一个\0表示字符串结束),可以用数组名,或者指针来处理。
#include <stdio.h>
int main()
{
chara[]="hello,world!";
char*p=a;
printf("%s\n",a);
printf("%s\n",p);
return0;
}
拷贝字符串的方法:
用字符数组:
#include <stdio.h>
int main()
{
chara[]="hello,world!",b[20];
for(inti=0;*(a+i)!='\0';i++)
*(b+i)=*(a+i);
*(b+i)='\0';
printf("%s\n",a);
printf("%s\n",b);
return0;
}
用指针变量来处理:
#include <stdio.h>
int main()
{
chara[]="hello,world!",b[20],*pa=a,*pb=b;
while(*pa!='\0')
*pb++=*pa++;
*pb='\0';
printf("%s\n",a);
printf("%s\n",b);
return0;
}
5.指向函数的指针
什么是函数指针:
如果在程序中定义了一个函数,编译系统为函数代码非配了一段存贮空间,这段存储空间的起始地址(又称入口地址)称为这个函数的指针。
如何定义函数指针:
类型名 (*指针变量名)(函数参数列表);
如int (*p)(int ,int );
p是指向一个返回类型是int,有两个int参数的函数
赋值:如p=max;
用函数指针调用函数:
如: c=(*p)(a,b);
注意:对指向函数的指针的不能做算术运算。如p++,p—等,这是无意义的。
用指向函数的指针作为参数:
如:void fun(int (*x1)(int ),int (*x2)(int ,int ))
{
int a,b,i=3,j=5;
a=(*x1)(i);
b=(*x2)(j);
}
6.返回值是指针的函数
类型名 *函数名(参数列表);
如:int *fun(int a);
返回值是指向int型数据的指针
7.指针数组和多重指针。
int *p[4];含有4个指向int型数据的指针变量
int **p; 指向一个int型的指针变量
8.动态内存分配
全局变量,分配在内存的静态存储区;非静态的局部变量(包括形参)分配在内存的动态存储区,这个存储区称为栈(stack)。
此外,C语言还允许建立内存动态分配区域,以存放一些临时的数据,这些数据不必在程序的声明部分定义,可以在需要时开辟,不需要时释放。这些数据临时存放在一个特别自由的存储区,称为堆区(heap)
C语言对内存的分配主要有这四个函数:
包含在#include<stdlib.h>
1.malloc函数
其函数原型为:void *malloc(unsigned int size);
作用:
在堆中分配一个长度为size的连续空间。指针void表示指针的基类型不指向任何类型的数据,只提供一个地址。
未成功执行,返回NULL
如:
int*p;
p=(int *)malloc(sizeof(int));
//注:可以不用显示的进行(int*)格式转换,C语言编译时会自动隐式转换。
2.calloc函数
函数原型:
void *calloc(unsigned n,unsigned size);
分配n个大小为size的连续空间。
可以为一维数组分配空间
3.free函数
函数原型:
void free(void *p);
p是最近调用malloc或calloc函数生成的指针
4.realloc函数
函数原型:
void*relloc(void *p,unsigned int size);
改变已经分配的p所指的空间的大小。P的值不变