不再怕指针

本文深入探讨了C语言中的指针,包括指针的类型、运算规则以及指针与数组的密切联系。通过实例解析了指针的算术运算,如加减操作,并强调了指针算术与数值运算的区别。同时,解释了指针运算符`&`和`*`的用法,并展示了指针表达式的概念。最后,阐述了指针如何作为数组名的别名,以及在数组操作中的应用。
摘要由CSDN通过智能技术生成

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’ 的地址。注意: 字符串相当于是一个数组, 在内存中以数组的形式储存,只不过字符串是一个数组常量,内容不可改变, 且只能是右值。如果看成指针的话,他即是 常量指针,也是 指针常量。
注:关于常量指针及指针常量------->
常量指针:这个指针是一个常量,当指向某个地址后就不可改变了,但是之子想的单元是可以改变的。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值