指针
&与*是两个作用相反的运算符。
二级指针只能保存一级指针变量的地址和指向指针数组,其余情况不考虑。
int *p[2]; int a=12; int b=15; *p=&a; *(p+1)=&b; printf("%d\n%d\n",**p,**(p+1)); int **r=p; printf("%d\n",**r);
普遍变量名是一个值,数组名等属于一个指针常量(即前者为一个值,后者是一个地址)
对于二维字符数组,话不多说看代码
char p[][5]={"1951","hell","than"}; printf("%s\n",*p);//1951 char p2[][5]={"19512","hell0","thank"}; printf("%s\n",*p2);//19512hell0thank char p2[][5]={ {'1','9'},"hell0","thank"}; printf("%s\n",*p2);//19
使用%s输出字符串时,printf第二个参数必须是地址
sizeof(指针)的值是4(个别操作系统是8),因为指针的值实际上是无符号整数(unsigned int),注意指针常量除外
int arr[10]; printf("%d\n",sizeof(arr));//40 int *p=arr; printf("%d\n",sizeof(p));//4
指针数组就是保存指针的数组(每一个数组元素都是一个地址)
int b=10,c=23,*a[2]={&b,&c}; printf("%d\n",**a);//10
指针在做函数参数带回返回值时,在函数内对该指针指向的地址进行更改可以影响到外面的指针,但是对该指针的值进行改变不会影响外面的指针
void fn(int *p,int A){ p=&A;//首先对p进行赋值,不会影响到外面的值,其次形参A在函数调用后地址会销毁。 } int main(){ int *p=NULL; int A=12; fn(p,A); printf("%d\n",*p);//报错! }
函数使用指针带回返回值时,对于一级指针来说有以下两种用法(切记不能初始化NULL再代入)
int a,*p=&a; fn(&a);//或者p printf("%d\n",*p);//12
初始化为NULL的指针不允许访问值和改变。
int *p=NULL; printf("%d\n",*p);//报错
初识指针与指针变量
指针:指针就是地址。(因地址指向变量的存储单元,故形象的将地址称为指针)
指针变量:用于保存地址的变量。指针变量的值就是地址,用来指向一个变量、函数、数组等。(即指针)
c语言对变量的访问本质上都是通过地址访问的,分为直接访问与间接访问(每定义一个变量,系统自动为该变量分配内存空间,变量名指向的是这片内存空间的首地址,故直接访问直接引用变量名,间接访问只是使用指针变量保存这个地址再通过引用指针访问)
内存以字节为单位,一个字节就是一个内存单元。例如一个int基类型变量占用4个存储单元。
c语言的内存地址是一个无符号整数。
普通变量前面不要加*就可以按地址访问是因为普通变量不是指针变量(数组名是一个指针常量)
c语言对变量的访问实质上是访问变量所占用的内存单元。
指针变量的定义与初始化
定义:
格式:数据类型 *标识符 例如 int *p; 指针变量的初始化可以在定义时初始化,也可以定义之后初始化(两者无条件等价) 例如 int *p=&a; int *p; p=&a;(注意这里不能使用*p) 指针变量初始化指向的对象一般是变量、数组、函数等
在定义时*是区别指针变量与其他变量的字符。调用时表示指针运算,即取指向对象的值或该对象。算数表达式中表示乘
指针变量的最左边的数据类型称为指针变量的基类型,它指定该指针变量可以指向的变量类型,不能省略(即指针变量是基本数据类型派生出来的类型,不能离开基类型而单独存在)
指针变量只能指向同类型的变量,所以初始化时应保证=两边的数据类型一致。(指针变量保存的是变量在内存中的首地址,地址都是无符号整型。例如int类型指针可以保存一个float类型变量的地址,因地址都是无符号整型,但是这个int指针却无法指向这个float类型变量,因数据类型不同)
在说明一个指针时要说明其是指向什么类型的指针
指针变量只能保存地址,即不能赋常量或自己给一个地址。但是空指针允许赋值为0或者NULL。例int *p=0(NULL)。
此外int类型指针初始化一个常量值编译可以通过,但是概念上是错误的。例如 int *p=100。
未初始化的指针变量指向的是一个随机地址。
切记不要使用未初始化的指针
int main(){ void fn(int *); int *s; fn(s);//报错,因为传入的指针s未初始化,指向一个随意的空间 } void fn(int *s){ *s=12; }
常见的指针初始化
指针=&变量名 指针=数组名 指针=指针 指针=NULL(0)
NULL是标准头文件<stdio.h>中定义的符号常量。
所有类型的指针变量的内存占用都是4。(unsigned int)
使用指针常见的错误:
1.使用未初始化的指针 2.指针赋常量值 3.间接访问void类型指针 4.指针与初始化对象类型不一致。
未初始化的指针不能使用,但是未初始化的指针的地址可以使用。
void fn(int **p,int *b){ *p=b; **p=123; } int main(){ int a=12,*p; fn(&p,&a); printf("%d\n",*p); }
指针做函数参数时,指针本身的值不能改变,但是可以改变指针下面变量的值或指针的指向。
fun(int *p){ *p=12; } int main(){ int a; fun(&a);//传入a无法改变a的值,但是传入a的地址可以。 即指针做函数参数时,指针本身的值不能改变,但是可以改变指针下面变量的值或指针的指向。 一集指针: 如果函数参数是指针变量,那么不能改变指针变量的指向,此时是因为指针本身是按值传递的,但可以改变指针指向的变量的值。 如果是指针常量(即上面那样,一个变量的地址),那么也不能改变指针本身的值,但是此时的原因是因为是常量,依然可以改变其指向的变量的值 二级指针: 如果函数参数是指针,那么不能改变二级指针的指向,但是可以改变二级指针保存的一集指针的地址的指向,跟甚至改变这个一集指针指向的变量的值。 如果是指针常量(一个一集指针的地址),那么此时也不能改变指针本身的值,它也属于一个常量,是一集指针在内存中的地址,这个是无法改变的由系统分配的,但依然可以改变其指向的指针的值,跟甚至改变这个一集指针指向的变量的值。 }
指针变量的引用
引用:
对指针变量的引用分为三种情况: 1.给指针变量单独初始化 例如 int *p; p=&a;(注意这里不能加*,否则表示的是该指针指向的对象) 2.引用指针变量指向对象的值: 例如 int *p=&a; *p=100; printf("%d\n",*p); 3.引用指针变量的值(一般没意义) 例如 int *p=&a; printf