C 语言 指针(二)

    目录

数组指针

           一维数组与指针

                  如何用指针使用数组

                 数组元素的引用方式

         二维数组与指针

         指向二维数组首地址的指针变量

        指向二维数组中某个一维数组的指针变量

字符串与指针

将指针变量指向字符串常量

指向字符串常量指针变量的使用

结构体指针

 指向结构体变量的指针

 指向结构体数组的指针

 用结构体变量作为函数参数


数组指针

  • 一维数组与指针

指针表示地址,数组名对应着数组的首地址,所以可以通过指针访问数组元素

数组通过数组名+下标的方式访问元素

数组的指针就是数组所在的存储区域的起始地址

数组元素的指针就是数组元素存储单元的地址

例:

#include<stdio.h>
int main()
{
	int arr[5]={0,1,2,3,4},i,*p;
	p=NULL;
	printf("%d\n",p);//printf函数直接显示指针地址,运行结果为0
	p=arr;
	printf("%x *p=%d\n",p,*p);//%x 表示输出16进制,*p=0,这时p指向数组的首地址,输出的值就是数组首个元素的值
	for(i=0;i<5;i++)
	printf("%x *p=%d\n",p++,*p);
	return 0;
}

 运行结果如下:

数组名代表数组首地址,即数组这首个元素的地址

a与&a[0]等价:a是地址常量,是系统分配空间时返回的地址,不是变量不能给af赋值

如果能赋值就是重新指一段连续的空间了

 如何用指针使用数组

1.指向数组首地址的指针变量的定义及赋值方式

(1)定义的同时进行初始化赋值

类型 *指针变量名=数组名或&数组名[0]

(2)先定义后赋值

类型 *指针变量名;

指针变量名=数组名或&数组名[0]

2.指向数组元素的指针变量的定义和赋值方式

(1)定义的同时进行初始化赋值

类型 *指针变量名=&数组名[下标];

(2)先定义后赋值           

 类型 *指针变量名

 指针变量名=&数组名[下标]

 注意:定义和赋值中的类型要与数组的基类型一致

            定义指针类型一定与数组的类型相同

例子:

#include<stdio.h>
void f(int *x,int *y)//函数f的参数是指向整型数据的指针,传递的是地址 
{
	int t;
	t=*x;
	*x=*y;
	*y=t;//这三个赋值语句是对指针所指单元的进行交换 
}
main()
{
	int a[8]={1,2,3,4,5,6,7,8},i,*p,*q;
	p=a;q=&a[7];//指针变量p取a的首地址,q取a7的地址 
	while(p<q)//用指针比较,也就是地址的比较 
	{         //在数组中元素单元实际地址是(首地址 +下标 )*4 
		f(p,q);p++;q--;
	}
	for(i=0;i<8;i++)
	    printf("%d,",a[i]);
}

过程分析:

/函数f的功能是交换两个 参数变量的值 
x,y作为形参,p、q为数组元素的地址作为实参 ,改变形参指针对应单元的值,实际就是修改实参变量单元的值
在函数中对数组的操作实际上是对主程序中的实参数组操作 
main()函数中执行了4次循环 ,实现了a[0]与a[7]、a[1]和a[6]、a[2]和a[5]、a[3]和a[4]的交换 

 运行结果如下:

 数组元素的引用方式

1.下标法

main()
{
    int a[10],i;
    for(i=0;i<10;i++)
    scanf("%d",&a[i]);
    printf("\n");
    for(i=0;i<10;i++)
    printf("%d",a[i]);
    
}

 2.指针法

main()
{
    int a[10],*p,i;
    p=a;//取初始地址,数组首地址
    for(i=0;i<10;i++)
    scanf("%d",p++);
    printf("\n");
    for(p=a;p<(a+10);p++)//用数组+1,表示取下一个单元地址。 用数组-1,表示取上一个单元地址。不是地址值的加减1
    printf("%d",*p);
}

  • 二维数组与指针

例:输出两行三列的矩阵元素

#include<stdio.h>
int main()
{
	int a[2] [3],*p,i,j;
	for(i=0;i<2;i++)
	  for(j=0;j<3;j++)
	  {
	  	p=&a[i][j];
	  	scanf("%d",p);//p代表地址在输入函数中,实现输入数据到相应的存储单元
	  }
	  for(i=0;i<2;i++)
	  {
	  	printf("\n");
	  	for(j=0;j<3;j++)
	  	{
	  		p=&a[i][j];
	  		printf("%4d",*p);//*p表示p指示相应存储单元的值
		  }
	  }
}

 本例中,指针变量都是指向数组具体的某一个存储单元,和数组名是有区别的

1.指向二维数组首地址的指针变量

(1)定义的同时赋初始值

数据类型*指针变量=&二维数组名[0][0];

(2)先定义后赋值

 数据类型*指针变量;

 指针变量=&二维数组名[0][0];

注:定义时用首元素地址时,不是用数组名,也不能用。因为数组名在二维数组中代表首行地址。可以理解为二维数组是一维数组的推广,也就是N维数组也是一维数组。其元素有N-1维数组构成,也就是二维数组名代表首行地址。这与首元素地址有很大区别:表现在指针移动上。一维数组有X个元素。地址只能往后移动X-1次

例:使用指向二维数组首地址的指针变量

#include<stdio.h>
int main()
{
	int a[2][3]={0,1,2,3,4,5},*p=a,i,j;
	for(i=0;i<2;i++)
	{
		printf("\n");
		printf("%x",p+i*3);
		for(j=0;j<3;j++)
		{
			printf("%x ",p+i*3+j);
			printf("%d ",*(p+i*3+j));
		}
	}
	printf("\n");
	return 0;
}

 2.指向二维数组中某个一维数组的指针变量

(1)定义指针变量

数据类型(*指针变量)[m];

m:二维数组的列长,()不能丢。不能写成“*指针变量[m]”,因为[ ]运算符优先级高于*

(2)将指针变量指向二维数组的首地址

定义时赋初值

数据类型(*指针变量)[m]=二维数组名;

先定义,后赋值

数据类型(*指针变量)[m];

指针变量=二维数组名

(3)二维数组中第i行对应的一维数组首地址表示

*(指针变量+i) 

(4)数组元素地址

*(指针变量+行下标)+列下标 

(5)数组元素引用

*(*指针变量+行下标)+列下标) 

例:

int a[2][3],(*p)[3]=a;

则有如下等价关系成立:a[i]等价于*(p+i)表示第i行地址

a[i][j]等价于*(*(p+i)+i表示第 i 行第j列元素

字符串与指针

1.将指针变量指向字符串常量

(1)

数据类型  *指针变量=字符常量;

例:char *p="abcd";

(2)

数据类型  *指针变量;

指针变量=字符串常量;

char *p;

p="abcd";

2.指向字符串常量指针变量的使用

输出字符串常量:

printf("%s",指针变量);

第i个字符的表示方法:  *(指针变量+i);

注意:

对指向字符串常量的字符型指针进行再输入会出现错误

例如:  char *p="1234";

            scanf("%s",p);   是错误的,因为p已经指向了一个常量区域,就不能用输入改变常量的值了

定义的字符数组可以输入

例如:char a[10],*p=a;

            scanf("%s",p); 

例:字符串的复制

#include<stdio.h>
int main()
{
	char a[]="Hava Fun",b[20];
	int i;
	for(i=0;*(a+i)!='\0';i++)//表示数组a的字符不是反斜杠0就继续,用的是指针访问数组a
	        *(b+i)=*(a+i);//把数组a的值一个一个赋给b
	        *(b+i)='\0';
	        printf("b:");//循环结束后,把反斜杠0送给b
	        for(i=0;b[i]!='\0';i++)
	        printf("%c",b[i]);//使用循环数组对数组b逐个字符输出
	        printf("\n");
	        return 0;

}

结构体指针

1.指向结构体变量的指针

定义:指向结构体变量的指针为结构体指针,它保存了结构体变量的存储首地址

结构体指针的定义形式:

struct  结构体类型名  *指针变量名;

例如:  struct student stu,*p;

要引用结构体变量p,就要把已存在的结构体变量的地址赋给它

比如p=&stu;(p指向stu)

此时指针变量p的值就是结构体变量stu的起始地址

结构体成员变量的引用形式

  •    结构体变量名.成员名;
  • (*结构体指针).成员名
  •    结构体指针->成员名;

例如:stu.age=20;

          (*p).age=20;

          p->age=20;  其中->为指向成员运算符 

指针变量也可以用来指向结构体数组中的元素,只要改变指针变量的值就可以通过它访问结构体数组中的各个元素

例如:

struct person{
        char name[10];
        int age;

    };

struct person *p,s,boy[3]={"Zhang",18,"Wang",20,"Li",17};

p=boy;

定义了结构体数组boy和结构体指针变量p,p=boy,代表p指向数组boy的首地址

相当于p=&boy[0]

2.指向结构体数组的指针

例:使用指针变量输出boy数组中的元素

#include<stdio.h>
int main()
{
	int i;
	struct person{
		char name[10];
		int age;

	}*p,boy[3]={"Zhang",18,"Wang",20,"Li",17};
	for(p=boy,i=0;i<3;i++)
	printf("%s %d\n",p[i].name,p[i].age);

}

运行结果如下: 

 3.用结构体变量作为函数参数

结构体变量作为函数参数,实现值传递

指向结构体的指针(或数组)作为函数参数,实现地址传递

#include<stdio.h>
struct stu
{
	int num;
	float score;
};
void f(struct stu *p)
{
	struct stu s[2]={
		{01,96},{02,89}
	};
	(*p).num=s[1].num;
	(*p).score=s[1].score;
}
main()
{
	struct stu s[2]={
		{03,93},{04,96}
	};
	f(&s[0]);
	printf("%d %3.0f\n",s[0].num,s[0].score);
}

运行结果如下:

  • 3
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值