本篇我主要写了以下四点关于指针的问题
- 字符指针与字符串
- 指针数组
- 多级指针
- void 和const 指针
首先感谢大家的观看,如果大家能有所收获,那真是荣幸之至
一、字符指针与字符串
-
C语言通过使用字符数组来处理字符串,通常,我们把char数据类型的指针变量称为字符指针变量。字符指针变量与字符数组有着密切关系,它也被用来处理字符串。
-
初始化字符指针是把内存中字符串的首地址赋予指针,并不是把该字符串复制到指针中,此时可以通过指针来修改字符串的内容
char str[] = “Hello World”;
char *p = str;
printf("&str=%p %s\n",&str,str);
*p='h'; *(p+1)='E';
printf("p=%p %s\n",p,p);
由此可以看出,p指向的str的首地址,可以根据p指针来修改字符串的值。如果有人对上述用*p修改有疑问,可以参考我上一篇博客,C语言指针简介与相关的难点
非常重要
- 在C编程中,当一个字符指针指向一个字符串常量时,不能修改指针指向的对象的值。当你直接将字符串赋值给指针时,该字符串会被认为是常量,会被存放在静态区域,所以此时不能修改。
char *p = "Hello World";
*p = 'h'; // 错误, 字符串常量不能修改
char *p1 = "Hello World";
char *p2 = "Hello World";
printf("%p\n",&"Hello World");
printf("&p1=%p p1=%p %s\n",&p1,p1,p1);
printf("&p2=%p p2=%p %s\n",&p2,p2,p2);
由结果可知,两个不同指针被赋予相同的字符串被认为是一个常量存放在静态区,两指针都指向的是该常量的地址
- 使用指针完成字符串的链接操作
#include<stdio.h>
int main(){
char ch[50] = "Hello";
char *p = "World";
int i = 0;
while( ch[i]!='\0') //找到原字符串的末尾
i++;
while( *p != '\0'){ //链接
*(ch+i) = *p;
i++; p++;
}
*(ch+i) = *p; //在字符串末尾加上结束符
puts(ch);
}
二、指针数组
- 所谓指针数组是指由若干个具有相同存储类型和数据类型的指针变量构成的集合
- 指针数组的一般说明形式:
<数据类型> *<指针数组名>[<大小>];
指针数组名表示该指针数组的起始地址
//声明一个指针数组:
double * pa[2] ,a[2][3];
//把一维数组a[0]和a[1]的首地址分别赋予指针变量数组的数组元数pa[0]和pa[1]:
pa[0]=a[0] ; // 等价pa[0] = &a[0][0];
pa[1]=a[1]; // 等价pa[1] = &a[1][0];
//此时pa[0]指向了一维数组a[0]的第一个元素a[0][0], 而pa[1]指向了一维数组a[1]的第一个元素a[1][0]。
//则a[0][1]就可以用 p[0]+1表示;
指针数组名是个什么指针?
int *p[2];
q = &p[0] ; //q的定义是什么?
由指针数据的定义的格式可知指针q的定义如下: <数据类型> * q
该<数据类型>取决于目标的类型,及p的类型,而p的类型为int *所以q的定义为: int ** q;这是一个二级指针。
三、多级指针
-
多级指针的定义
把一个指向指针变量的指针变量,称为多级指针变量
对于指向处理数据的指针变量称为一级指针变量,简称一级指针
而把指向一级指针变量的指针变量称为二级指针变量,简称二级指针 -
二级指针变量的说明形式如下
<数据类型> ** <指针名> ; -
多级指针的运算
- 指针变量加1,是向地址大的方向移动一个目标数据。类似的道理,多级指针运算也是以其目标变量为单位进行偏移。
- 比如,int **p;p+1移动一个int *变量所占的内存空间。再比如int ***p,p+1移动一个int **所占的内存空间。
int a[] = {3, 6, 9};
int *p[2] = {&a[0], &a[1]};
int **q;
q = &p[0]; //等价为q=a;
printf("%d %d %d\n",a[0],*p[0],**q); //a[0]的表示方法
printf("%d %d %d\n",a[1],*p[1],**(q+1));//a[1]的表示方法
printf("%d %d %d\n",a[2],*(p[1]+1),*(*(q+1)+1));//a[2]的表示方法
- 由图可知,p[0],p[1]存的是a[0],a[1]的地址,所以p[0]表示a[0]的存的值,q存的是p[0]的地址,故q就表示p[0]的值,及a[0]的地址,所以**q就表示a[0]的值。
- a[3]的地址可由a[2]的地址+1表示,即p[1]+1;同理,p[1]的地址可由q+1表示。所以a[3]的地址等价于 *(q+1)+1。
- 不要问我为什么a[3]不能用q+2表示,这说明你还是没有理解,上面这个图的结果是从右往左推出来的,而不是从左往右推的,实在理解不了,自己画个图理解下或者自己编程看看q+2的地址是啥
四、void和const指针
1. void指针
是一种不确定数据类型的指针变量,它可以通过强制类型转换让该变量指向任何数据类型的变量
一般形式为: void * <指针变量名称> ;
对于void指针,在没有强制类型转换之前,不能进行任何指针的算术运算。
2. const修饰指针
关于const修饰,总之记住一句话:const修饰谁,谁不能改变。
1)常量化指针目标表达式
- 一般说明形式如下:
const <数据类型> * <指针变量名称>[= <指针运算表达式>] ;
常量化指针目标是限制通过指针改变其目标的数值 ,但<指针变量>存储的地址值可以修改
int m=10;
const int *p = &m;
p = &n; //right
(*p)++; //error, const修饰*p ,所以*p不能改
2)常量化指针变量
- 一般说明形式如下:
<数据类型> * const <指针变量名称>[= <指针运算表达式>] ;
使得<指针变量>存储的地址值不能修改。但可以通过*<指针变量名称> 可以修改指针所指向变量的数值
int m = 10;
int * const q = &m ;
(*q)++; //right
q = &m; //error ,只能在定义时初始化
3)常量化指针变量及其目标表达式
- 一般说明形式如下:
const <数据类型> * const <指针变量名> = <指针运算表达式> ;
常量化指针变量及其目标表达式,使得既不可以修改<指针变量>的地址,也不可以通过*<指针变量名称>修改指针所指向变量的值