指针速览笔记【沈七】

前言

⭐️感谢相遇,唤我沈七就好。
⭐️如果能和你一起进步那就太好啦。

指针变量

基本概念

指针变量:存储其他变量的指针的变量

**变量的指针:变量的地址 **

*记为 : int p = & a;

易错点

指针变量的交换

**访问 p 相当于直接访问地址所在元素,所以修改 p ,其存储地址所在的元素也会被修改

//通过改变指针的变量 间接的改变  a b 变量的值
#include<stdio.h>
void swap(int * pa ,int *pb)
{
    
    
	int t;
	t=*pa,*pa=*pb,*pb=t;
}
int main()
{
    
    
    int a,b;
    int *pa = &a,*pb = &b;
    scanf("%d%d",&a,&b); 
    if(a<b)
    swap(pa,pb);
    printf("%d %d",a,b);
 
}

而直接修改 p 存储的地址,不会影响到其原来存储地址所在的元素的值,改变的是指针的指向

//分别指向 a b 的指针变量 变成 分别指向b a的指针变量
int main()
{
    
    
  int a,b;
  int *pa = &a,*pb = &b,*t;
  scanf("%d%d",&a,&b); 
  if(a<b)
  t=pa,pa=pb,pb=t;
  printf("%d %d\n",a,b);
  printf("%d %d",*pa,*pb);
}

注意如果要将 仅交换指针的功能 封装成函数的话,那这样只改变的是指针的指向的方法就不对了。

因为在自定义函数中接受指针变量的是形参变量,参变量只有在函数被调用时才会分配内存,

调用结束后,立刻释放内存,所以形参变量只有在函数内部有效,不能在函数外部使用。

函数指针

声明 :int (*p)(int ,int)

一维数组

指向数组的指针变量

int a[5],*p;

p = a;

p = & a[0];

数组的地址就是 数组名 或者 &+数组中第一个元素 即 &a[0]

*(p + i ) 是 a[i]

给 a 数组 赋值

for(int p = a, i = 0 ; i < 10 ; i ++, p ++)

*p = i;

打印 a 数组 的值

for(int p = a ; p <(a+10) ; p ++)

printf(“%d”,*p);

p + 1 指向 数组的下一个元素

**(p)++ 和 p++

1.变量维度

int *p = &a

*** p++ 代表的是 p 储存的 地址 + 1 ,( * p)++ 代表的是在 p 储存的地址 上的值 + 1**

2.数组维度

int a[1000]

int * p = a

p为a 的首地址 , p 即表示 a数组中的第一个元素*

*p++ 即将地址自增 表示的就是 a数组中的第二个元素

*(p+i)代表的就是a[i]的值

*p)++ 表示a 数组中的第一个元素自加

二维数组

a [100] [100]

行指针

int (*p)[4]=a;

行指针:指的是一整行,不指向具体元素。

a &a[i] a+i

行指针+i 和这一行的元素个数和数据类型有关

数组名依然是数组的指针,只不过在二维数组里只代指行指针

用行指针输出整个二维数组

#include<stdio.h>
int main()
{
    
    
   float a[4][4];
   float (*p)[4]=a;//float (*p)[4]=&a[0];
   
   for(int i = 0 ; i < 4 ; i ++)
   for(int j = 0 ; j < 4 ; j ++)
   scanf("%f",&a[i][j]);
   
   for(i = 0; i < 3; i++)
   for(j = 0; j < 4; j++)
   printf("%d ",*(*(p + i) + j));
   printf("%d ",*(   p[i]  + j));
   
   return 0;
}

列指针

int * p = a [0] ;

列指针:指的是一行中某个具体元素。

*a a[i] a[i] [j] *(a+i) a[i]+j

*( a[1] + 12 )== a[0] [12]

*( *(a+1)+12)==a[0] [12]

列指针+i 只和数据类型有关

可以将列指针理解为行指针的具体元素,行指针理解为列指针的地址。

用列指针输出整个二维数组

#include <stdio.h>
int main()
{
    
    
    int a[3][4]={
    
    1,3,5,7,9,11,13,15,17,19,21,23};

    int *p= a[0];   // 列指针的定义法
    
    for(; p < a[0] + 12; p++) 
	printf("%d ",*p);
    printf("%",*(p+i * 7 + j ))
    return 0;
}

那么两个概念之间的具体转换是:

行指针*----** 列指针

& 列指针 ---- 行指针

*p = &a[0] [0]

*(p+i * 7 + j )

(*p)[7]=a

a;//代表数组首行地址,一般用a[0][0]的地址表示

&a;//代表整个数组的地址,一般用a[0][0]地址表示

*a;//代表数组a首元素地址也就是a[0]或者&a[0][0]

a[i];
代表了第i行起始元素的地址
  (网上说是代表了第i行的地址,但我觉得不是,在讲数组与指针的关系时我会验证给大家看)
&a[i];代表了第i行的地址,一般用a[i][0]的地址表示
    
a[i]+j;//代表了第i行第j个元素地址,a[i]就是j==0的情况

&a[i][j];//代表了第i行第j个元素的地址

*(a+i);//代表了第i行首元素的地址,*a是i=0的情况

*(a+i)+j;//代表了第i行j个元素的地址

**a;//代表a的首元素的值也就是a[0][0]

*(*(a+i)+j);//代表了第i行第j个元素

配套习题

有了以上的知识储备后,在来几个配套习题加深理解~

1.编程,从键盘输入5个字符串,存入数组a中,编写程序,找出其中最大字符串并输出,要求使用指针完成。

#include<stdio.h>
#include<string.h>
int main()
{
    
    
	char a[10][10],str[10];
	char (*p)[10];
	p = a ;
	for(int i = 0 ;  i < 5 ; i ++)
	scanf("%s",a[i]);
	strcpy(str,p[0]);
	for(int i = 0 ; i < 5 ; i ++)
	if(strcmp(str,p[i])<0)
	strcpy(str,p[i]);
	printf("%s",str);
	return 0;
}

2.编程,在主函数中输入10个最长不超过20个字符的字符串,用另一个函数完成对这10个字符串降序排序,然后在主函数中再输出排序后的字符串。

#include<stdio.h>
#include<string.h>
int n;
void sort(char (*p)[20])
{
    
    
	char *t;
	for(int i = 1 ; i < 10; i ++)
	for(int j = 0 ; j < 10- i ; j ++)
	if(p[j+1]>p[j])
	*t = *p[j+1], *p[j+1]=*p[j], *p[j]=*t; 
}
int main()
{
    
    
	char a[10][20],str[10];
	char (*p)[20];
	p = a ;
	for(int i = 0 ;  i < 10 ; i ++)
	scanf("%s",a[i]);
	sort(a);
	for(int i = 0 ;  i < 10 ; i ++)
	printf("%s\n",a[i]);
	return 0;
}

3.a数组是6*6的二维int型数组,其元素值由键盘输入,请编程找出二维数组a中每行的最大值,并按一一对应的顺序存入一维数组s中。即:第零行中的最大值,存入s[0]中,第一行中的最大值,存入s[1]中,……。输出每行的行号和最大值。

#include<stdio.h>
int a[6][6],s[6],b[6];
void find(int (*p)[6],int *s,int *b)
{
    
    	
	for(int k = 0 ; k < 6 ; k ++)
	for(int i = 0 ; i < 6 ; i ++)
	for(int j = 0 ; j < 6 ; j ++)
	if(*(s+k)<*(*(p+i)+j))
	*(s+k)=*(*(p+i)+j),*(b+k)=j;
}
int main()
{
    
    	

	for(int i = 0 ; i < 6 ; i ++)
	for(int j = 0 ; j < 6 ; j ++)
	scanf("%d",&a[i][j]);
	find(a,s,b);
	for(int i = 0  ; i < 6 ; i ++)
	printf("行号为%d 最大值为%d \n",b[i],s[i]);
	return 0;
}

4.用指针编程,输出6*6方阵a中两个对角线上元素之和。

#include<stdio.h>
#include<string.h>
int sum(int (*p)[6])
{
    
    
	
	int s = 0;
	for(int i = 0 ; i < 6 ; i ++)
	s=s+*(*(p+i)+i)+*(*(p+i)+5-i);
	
	return s;
}
int main()
{
    
    
	int a[6][6];
	for(int i = 0 ; i < 6 ; i ++)
	for(int j = 0 ; j < 6 ; j ++)
	scanf("%d",&a[i][j]);
	
	printf("%d",sum(a));
	return 0;
}

完结散花

ok以上就是对 C语言指针 的全部讲解啦,很感谢你能看到这儿。如果有遗漏、错误或者有更加通俗易懂的讲解,欢迎小伙伴私信我,我后期再补充完善。

参考文献

https://www.acwing.com/activity/content/19/

猜你喜欢

转载自blog.csdn.net/m0_66139206/article/details/124534787
今日推荐