指针是什么:
指针是编程语言中的一个对象,利用地址,它的值直接指向存在电脑存储器中另一个地方的值。由于通过地址能找到所需的变量单元,可以说,地址指向该变量单元。因此将地址形象化的称为“指针”。是通过它能找到以它为地址的内存单元。
指针存在的意义:
1.指针是地址,用来存放地址,地址唯一标识一块内存空间
2.指针的大小是固定的4/8个字节(32位平台/64位平台)
3.指针是由类型,指针的类型决定了指针的±整数的步长,指针解引用操作的时候的权限
4.指针的运算 (指针-指针(指向同一内存),算的是两地址之间相差的元素个数)
# include <stdio.h>
# include <stdlib.h>
int main ()
{
int n=10; //在内存中开辟一块空间(4个字节)
char *pc=(char *)&n;
int *pi=&n; //将n的地址存放在指针变量中,p就是一个指针变量
printf ("%p\n",&n);
printf ("%p\n",pc);
printf ("%p\n",pc+1); //差1
printf ("%p\n",pi);
printf ("%p\n",pi+1); //差4
printf ("%d\n",sizeof (char *));
printf ("%d\n",sizeof (int *)); //32平台
system ("pause");
return 0;
}
指针类型
指针的定义方式:type +*,char * 类型指针是为了存放char类型变量的地址,其他的也可类比。
常见的指针类型有:(int *),(short *),(double *),(int (*P)[] 数组指针) , ( void (*pfun1)() 函数指针)等
指针常见易混淆名词
1.指针变量:指针变量是变量,可存储地址(数据),可变的是数值 。(指针变量的地址可存储在二级指针中)
2.变量指针:变量的地址,可变的是地址
3.地址<——>指针
4.void x,使用编辑器时报错,因为无法开辟地址,因此不能定义变量 ,不同平台中sizeof (void) 的大小不一样,但是都存在错误。
void *x,可用 void 定义 x,它可以接受任意类型,但是不能被解引用 (void 是指针,所以32平台为4)
二级指针:
指针变量也是变量,是变量就有地址,那指针变量的地址存放在哪里?这就是二级指针,a的地址存放在pa中,pa的地址存放在ppa中,pa是一级指针,而ppa是二级指针
- *ppa通过对ppa中的地址进行解引用,这样找到的是pa,*ppa其实访问的就是pa
int b=20;
*ppa=&b; //等价于pa=&b;
- **ppa先通过*ppa找到pa,然后对pa进行解引用操作 : *pa,找到的是a
***ppa=30;
//等价于*pa=30;
//等价于a=30;
数组:
数组是一组相同类型元素的集合
数组的创建方式:type_t arr_name [const_n]; //type_t 指数组的元素类型,const_n是一个常量表达式,用来指定数组的大小。
#define i 10
int arr1[i]; //可写成arr[i]<=>*(arr+i)<=>*(i+arr)<=>i[arr]
注:数组创建,[ ]中要给一个常量才可以,不能使用变量
数组的初始化:
数组的初始化是指在创建数组的同时给数组的内容一些合理的初始值
int arr[10]={2,3,4,5,6};
char str[ ]="abcde";
int num[][2]={{1,3},{2,5}};
数组在创建的时候如果想不指定数组的确定的大小就得初始化,数组元素的个数根据初始化的内容来确定,但是对一下代码要区分,在内存中如何分配
# include <stdio.h>
# include <stdlib.h>
# include <string.h>
int main ()
{
char arr1[]="abc";
char arr2[3]={'a','b','c'};
char arr3[4]={'a','b','c'};
printf ("%d\n",sizeof(arr1)); //4 包含'\0'
printf ("%d\n",sizeof(arr2)); //3
printf ("%d\n",sizeof(arr3)); //4
printf ("%d\n",strlen(arr1)); //3
printf ("%d\n",strlen(arr2)); //结果会随机,因为无'\0'
printf ("%d\n",strlen(arr3)); //3
system ("pause");
return 0;
}
数组不能被整体赋值,但可被全部初始化。
数组的存储及使用:
# include <stdio.h>
# include <stdlib.h>
int main ()
{
int arr[10]={0};
int i=0;
int sz=sizeof (arr)/sizeof (arr[0]); //计算数组元素个数
for (i=0;i<sz;++i) //数组是使用下标来访问的,下标是从0开始的
{
printf ("&arr[%d]=%p\n",i,&arr[i]);
}
system ("pause");
return 0;
}
结论:数组在内存中是连续存放的
二维数组的应用:
二维数组的创建和初始化和一维数组相同
# include <stdio.h>
# include <stdlib.h>
int main ()
{
int arr1[3]={4};
int *p1=arr1; //第一个元素的地址
int arr2[][5]={{4,2,6},{3}}; //行可省,列不可省
int *p2=arr2[5]; //表示第一行元素的地址
int a=sizeof (arr1)/sizeof (arr1[0]); //行元素个数
int b=sizeof (arr2[0])/sizeof (arr2[0][0]); //列元素个数
printf ("%p\n",p1);
printf ("%p\n",p2);
printf ("%d\n",a);
printf ("%d\n",b);
system ("pause");
return 0;
}
# include <stdio.h>
# include <stdlib.h>
int main ()
{
int arr[3][4];
int i=0;
int j=0;
for (i=0;i<3;i++)
{
for (j=0;j<4;j++)
{
printf ("&arr[%d][%d]=%p\n",i,j,&arr[i][j]);
}
}
system ("pause");
return 0;
}
结论:二维数组在内存中也是连续的
数组传参:
数组传参,如果函数内部需要知道数组元素个数,应该在函数外部算出元素个数,以参数的形式传递给函数。(数组作为函数的参数时,不会把整个数组都传递过去)
# include <stdio.h>
# include <stdlib.h>
//void fun(int arr1[],int z) //传参1
void fun(int *arr1,int z) //传参2
{
int i=0;
for (;i<z;i++)
{
printf ("%d ",arr1[i]);
}
printf ("\n");
}
int main ()
{
int arr[]={1,2,8,4,5,6,7,9};
int sz=sizeof(arr)/sizeof(arr[0]); //数组元素个数
fun (arr,sz); //函数调用
system ("pause");
return 0;
}
指针和数组名:
# include <stdio.h>
# include <stdlib.h>
int main ()
{
int arr[10]={1,2,3,4,5};
printf ("%p\n",arr); //数组名是首元素地址
printf ("%p\n",&arr[0]); //首元素地址
printf ("%p\n",&arr); //整个数组的地址(地址打印出来一样,但实质不同)
printf ("%d\n",sizeof(&arr)); //指针的大小
printf ("%d\n",sizeof(arr)); //表示整个数组大小
printf ("%d\n",sizeof(arr+1));//指针的int类型向前一步的距离
system ("pause");
return 0;
}
指针和数组:
# include <stdio.h>
# include <stdlib.h>
int main ()
{
int arr[]={1,2,3,4,5,6,7};
int *p=arr;
int i=0;
int sz=sizeof(arr)/sizeof(arr[0]);
for (i=0;i<sz;i++)
{
printf ("&arr[%d]=%p=>%d <===> p+%d=%p=>%d\n",i,&arr[i],arr[i],i,p+i,*(p+i));
}
system ("pause");
return 0;
}
p+i就是计算的是数组arr下标的地址,所以可通过指针访问数组,*(p+i)就是数组arr[i]中的内容
指针数组:
是数组,是存放指针的数组
# include <stdio.h>
# include <stdlib.h>
int main ()
{
int i=0;
int arr[][3]={{1,2,3},{4,5},{6,7}};
int sz=sizeof(arr)/sizeof(arr[0]);
for (i=0;i<sz;i++)
{
printf ("%d ",*(*(arr+i)));
}
system ("pause");
return 0;
}
int *arr[5] (整形指针数组,数组有5个元素,存放整形指针)