1、数组、数组名、数组首元素三者的地址的关系。
代码输出结果为:
由此可知数组名=数组的地址=数组首元素的地址。
1、指针数组
指针数组就是元素均为指针的一个数组,主体是数组,其定义形式为:类型名称 *数组名[数组长度],如:int *a[10]。
#include<stdio.h>
int main()
{
int i;
char *ptr[]={"Pascal","Basic","Fortran","Java","Visual C"};
for(i=0;i<5;i++)
{
printf("%s\n",ptr[i]);
}
return 0;
}
输出结果为:
指针数组ptr的每个元素ptr[i]都是指针,分别指向一个字符串。ptr[i]中存放字符串的首地址,因此每次输出的都是ptr[i]所代表的字符串。
3、数组指针
数组指针也称一维数组的指针或行指针,主体在于指针,其定义形式为 类型名称 (*指针名)[数组长度] ,如int(*p)[100],注意,不能写成int *p[100]的形式,因为[]的优先级高于*,[]会首先与p结合成int *(p[100]),使变量类型成为数组,int *为元素类型。
#include<stdio.h>
int main()
{
int a[5]={1,2,3,4,5};
int (*p)[5]=&a;
int i;
for(i=0;i<5;i++)
{
printf("%d\n",*(*p+i));
}
return 0;
}
输出结果为:
上面的代码中定义了一个指向含有五个int型数组的指针p,并让指针p指向a数组的首地址。
4、指针的隐式转换
在大多数包含数组的表达式中,数组自动转换成指向数组首元素的指针。也就是说数组名的值是指向数组第1个元素的指针。
#include<stdio.h>
int main()
{
int a[3]={1,2,3};
int *p=a;
printf("%p\n",a);
printf("%p\n",p);
printf("%d\n",*p);
printf("%d\n",a[0]);
}
但是这个规则也有例外
sizeof返回整个数组所占用的字节而不是一个指针所占用的字节。对数组执行sizeof运算得到整个数组所占大小,对指针执行sizeof运算得到指针本身的大小。
#include<stdio.h>
int main()
{
int a[3]={1,2,3};
int *p=a;
int l_1=sizeof(*p);//int类型指针占4个字节,对指针进行sizeof运算只能得到指针本身的大小
int l_2=sizeof(a);//而数组a中有三个元素,对数组进行sizeof运算得到4*3=12个字节
printf("%d\n",l_1);
printf("%d\n",l_2);
}
还有一个就是取地址符(&),当对数组取地址时,它返回的是一个指向数组的指针,而非一个指向指针的指针。
#include<stdio.h>
int main()
{
int a[3]={1,2,3};
int *p=a;
printf("%p\n",a);
printf("%p\n",p);
printf("%p\n",&a);
printf("%p\n",&a[0]);
printf("%p\n",&a[1]);
printf("%p\n",&a[2]);
}
5、指针与内存
malloc函数-----函数原型为 : void *malloc(unsigned size);
这个函数的功能是向系统申请大小为size的连续内存块,然后把首地址返回,如果申请不成功,则返回NULL。所以我们在用malloc()函数开辟动态内存之后, 一定要判断函数返回值是否为NULL。函数malloc()的返回值类型为void *(这是通用指针的一个重要用途),它可以指向任意类型的变量。
free()函数-----函数原型为void free(void *p);
这个函数的功能是释放由malloc() 函数申请的内存块,p指向此块的首地址,malloc() 函数向系统申请的内存块不会自己主动释放,如果我们不手动释放的话,可能会造成内存泄漏。所以当我们申请的动态内存不再使用时 ,一定要及时释放 。
#include<stdio.h>
#include<stdlib.h>
int main()
{
int n;
int *p=NULL;
scanf("%d",&n);
p=(int *)malloc(n*sizeof(int));//向内存中申请内存
if(p!=NULL)
{
for(int i=0;i<n;i++)
{
scanf("%d",&p[i]);
}
for(int i=0;i<n;i++)
{
printf("%d ",p[i]);
}
}
free(p);//释放内存之后,p=NULL;
return 0;
}
6、指针类型的重要性
不同类型指针所占的字节不同,int型指针占4个字节,char型指针占1个字节,double型指针占8个字节,但是指针的类型(即指针本身的类型)和指针所指向的类型是两个概念。如int *p,指针的类型是int*,但是指针所指向的类型是int。指针的值是指针所指向的内存区或地址,指针也可以进行算术运算,指针加或减一个整数还是指针,指针加或减指针是单位。
#include<stdio.h>
int main()
{
char a='a';
char *p1=&a;
int b=1;
int c=2;
int *p2=&b;
int *p3=&c;
printf("%p\n",p1);
printf("%p\n",p1+1);
printf("%p\n",p2);
printf("%p\n",p2+1);
printf("%p\n",p3);
printf("%p\n",p2-p3);
return 0;
}