0.指针漫谈
在了解指针时,我们会发现指针分为很多类型,有些类型里面会有很多运算符,这导致这些指针类型非常复杂,给初学者带来很多困扰。其实,复杂类型的指针也像一个表达式一样,可根据优先级进行解读,具体原则为:
从变量名开始,根据运算符优先级及结合性,一步步进行解读!
1.指针本身所占内存区
最常见的指针是一级指针(如*p),当然还有二级指针、三级指针等。想要知道指针的大小可以通过关键字sizeof()得知,在32位机内,指针本身占用4个字节,
2指针的算数运算
指针可以加上或减去一个整数,但是与数值加减不一样,它以单元为单位。但是两个指针不能进行加法运算,因为当两个指针进行加法运算时,指向的区域是一块不确定的区域,得到的结果可能是随机数或一个非法操作。两个指针可以进行减法操作,但是类型必须相同。
例子:
#if 0
/*
例1:指针与整数相加:
,如下代码中:
ptr1++;编译器处理方式:指针ptr的值加上sizeof(int)字节,在
32位程序中,即为4个字节,因为a的类型为char型以1字节为单位,所以
ptr1++后指向的地址由a[0]变为a[4]
* */
#include<stdio.h>
int main(int argc, const char *argv[])
{
char a[20] = {'a','b','c','d','e','f','g'};
int b[20] = {1,2,3,4,5,6,7,8,9};
int *ptr1 = (int *)a; //强制类型转换,并不会改变a的类型
int *ptr2 = (int *)b;
printf("*ptr1 = %c,*ptr2 = %d\n",*ptr1,*ptr2);
ptr1++;
ptr2++;
printf("*ptr1 = %c,*ptr2 = %d\n",*ptr1,*ptr2);
return 0;
}
#endif
#if 0
/*
例2:
*/
#include<stdio.h>
int main(int argc, const char *argv[])
{
int array[20] = {0};
int i = 0;
int *ptr = array;
for(;i<20;i++){
(*ptr)++; //指针指向的值加1
ptr++; //指针地址加1,所以下一次可以访问下一个地址单元指向的内容
}
return 0;
}
#endif
#if 0
/*
例3:
*在下面的例子中,因为ptr类型为int
所以ptr+=5编译器处理方式为:将指针
ptr向右(高位地址)移动5*4=20个字节
因为a存储char型数据大小为20,执行上述
操作后会使指针超出存储区,但是下面代码
无语法错误
*
*/
#include<stdio.h>
int main(int argc, const char *argv[])
{
char a[20] = "you-are-a-good-boy";
int *ptr = (int *)a;
ptr+=5;
return 0;
}
#endif
#if 0
/*
例4:
*下面再讲述一个指针误区:
在下面的例子中得出的结果:
正确:y 和一个随机数或非法操作
因为,32位程序中指针大小为4字节(几级指针都是),
ptr时char**类型,它指向的地址是P的地址即为&p,
当执行ptr++时,会使指针加sizeof(char*)即&p+4,
这个地址指向那就不得而知了。
* */
#include<stdio.h>
int main(int argc, const char *argv[])
{
char a[20] = "you-are-a-good-boy";
char *p = a;
char **ptr = &p;
printf("**ptr = %c\n",**ptr);
ptr++;
printf("**ptr = %c\n",**ptr);
printf("sizeof(p)=%d,sizeof(ptr)=%d\n",sizeof(p),sizeof(ptr));
return 0;
}
#endif
3指针运算符&和*
指针中:&是取地址运算符;是间接运算符
例:
int * a; //定义一个一级指针,指针类型为int ,指向内容为 *a ,指 向的类型为 int,指针所指向的地址是 &a;
4.指针表达式
定义:一个表达式 的结果如果为指针,则这个表达式为指针表达式。
例:
#if 0
/*
*指针表达式:结果为指针的表达式
* */
int a,b;
int array[10];
int *pa;
pa = &a; //是指针表达式
int **ptr = &b; //是指针表达式
ptr = &b; //*ptr和&b都是指针表达式
pa = array;
pa++; //这也是指针表达式
#endif
5.指针与数组的关系
指针与数组之间存在千丝万缕的关系,对于一个数组,可以将数组名看做一个指针。
例:
char *str[3]={
"Hello,thisisasample!",
"Hi,goodmorning.",
"Helloworld"
};
chars[80] ;
strcp y(s,str[0]); // 也可写成 strcpy(s,*str);
strcpy(s,str[1]); // 也可写成 strcpy(s,*(str+1));
strcpy(s,str[2]); // 也可写成 strcpy(s,*(str+2));
上例中,str 是一个三单元的数组,该数组的每个单元都是一个指针,这些指针各指向一个字符串。把指针数组名 r str 当作一个指针的话,它指向数组的第 0 0 号单元,它的类型是char ** ,它指向的类型是 char **。
*str也是一个指针,它的类型是 char **,它所指向的类型是 char,它指向的地址是字符串 “Hello,thisisasample!” 的第一个字符的地址,即 ‘H’ 的地址。注意: 字符串相当于是一个数组, 在内存中以数组的形式储存,只不过字符串是一个数组常量,内容不可改变, 且只能是右值。如果看成指针的话,他即是 常量指针,也是 指针常量。
注:关于常量指针及指针常量------->
常量指针:这个指针是一个常量,当指向某个地址后就不可改变了,但是之子想的单元是可以改变的。