C语言复习合集【10】指针:指针的用法、指针的概念、指针的含义、指针的运算、指针和数组、指针和二维数组、字符指针和字符串、指针数组、多级指针、void指针、const修饰指针

指针:~用法、概念、含义、运算、指针和数组、指针和二维数组、字符指针和字符串、指针数组、多级指针、void指针、const修饰指针

目录


前言

指针:~用法、概念、含义、运算、指针和数组、指针和二维数组、字符指针和字符串、指针数组、多级指针、void指针、const修饰指针

大家可以通过代码理解学习


一、指针用法

C语言中使用指针可以

1. 程序简洁,紧凑,高效
2. 有效的表达复杂的数据结构
3. 动态分配内存
4. 得到多余一个的函数返回值

在计算机内存中,每一个字节单元,都有一个编号,称为地址;

编译或函数  调用时为其分配  内存单元
变量 是 对程序中数据存储空间的抽象

二、指针概念

C语言中,内存单元的地址称为指针,专门用来存放地址的变量,有时对地址,指针和指针变量不区分,统称指针。(地址==指针)

指针变量的说明
一般形式:

<存储类型><数据类型* <指针变量名>

指针的英文名:pointer
例如:

char *p Name;
inta;

指针的存储类型是   指针变量本身存储类型

指针 说明时 指定的数据类型 不是 指针变量本身的数据类型,而是指针目标的数据类型,简 称为指针的数据类型。

指针在说明的同时,也可以被赋予初值,叫做指针的初始化。

一般形式是:

<存储类型><数据类型>*<指针变量名>=<地址量>;例如:
inta ,*pa=&a
inta=1;

在上面的语句中,把变量a的地址 作为 初值赋予了 刚说明的int型指针pa

用指针实现数字a,b的交换,可以通过以下代码理解学习

//用指针实现数字a,b的交换
#include <stdio.h>
void swap_3(int *p,int *q)
{
	int t;
	t=*p;
	*p=*q;
	*q=t;
}
 main(void){
	int a=3;
	int b=5;
	swap_3(&a,&b);
	printf("a=%d,b=%d\n",a,b);
}

三、指针含义

指针 指向的 内存区域中的数据 称为指针的目标

如果它指向的区域是程序的一个变量的内存空间,则这个变量称为指针的目标变量,简称 为指针的目标。

引入指针要注意程序中的px *px &px 三种表示方法的不同意义,设px为一个指针, 则:

px ,指针变量,它的内容是地址量

*px,指针所指向的对象,它的内容是数据

&px,指针变量占用的存储区域的地址,是一个常量

指针的赋值运算 指的是通过  赋值运算符  指针变量送一个地址值。

向一个指针变量赋值时,送的值必须是地址常量或指针变量,不能是普通的整数(除 了赋零以外)。

指针赋值运算常见的有以下几种形式:
  1. 把一个普通变量的地址  赋给一个 具有相同数据类型的指针

doublex=15 ,*px ;
               px=&x ;

 2.把一个已有地址值  的  指针变量  赋给具有相同数据类型的另一个指针变量

floata,*px,*py;
px=&a;
py=px;

3.把一个数组的地址  赋给具有  相同数据类型的指针

int  a[20], *pa;
 pa = a;  //等价于  pa = &a[0]

问题:什么是指针?

内存单元的地址 称为指针

指针有多少字节?

8

四、指针运算

1. 指针运算是以 指针变量  所存放的地址量  作为运算量而进行的运算。

2. 指针运算的实质  就是   地址的计算。

3. 指针运算的种类是有限的,它只能进行   赋值运算、算数运算 和 关系运算

指针的算术运算见下表:

运算符

计算形式

意义

+

px+n

指针向地址大的方向移动n个数据

-

px-n

指针向地址小的方向移动n个数据

++

px++++px

指针向地址大的方向移动1个数据

--

px----px

指针向地址小的方向移动1个数据

·

px·py

两个指针之间相隔数据元数的个数

//指针运算中的 算术运算
#include <stdio.h>
#include <stdlib.h>
 main(void)
 {
 	int a[5] = {1,2,3,4,5};
 	
 	int *pa,*pb;
 	pa = a;
 	pb = &a[3];  //4
 	
 	printf(" %p %d\n",pa,*pa);
 	printf(" %p %d\n",pb,*pb);
}

指针加减

注意:

1. 不同数据类型的两个指针  实行 加减法整数运算  是没有意义的

px+n表示的实际位置的地址量是:
        (px)+sizeof(px的类型) * n

两个指针相减运算

px-py运算的结果是  两个指针指向的地址位置之间    相隔数据的个数。因此两个指针相减       

不是两个指针持有的地址值   相减的结果。

两个指针相减的结果值不是地址量,而是一个整数值,表示两指针之间相隔数据的个数

px++,    ++px,   px--, --px运算

指针的关系运算符

运算符

说明

例子

>

大于

px>py

<

小于

px<py

>=

大于等于

px>=py

<=

小于等于

px<=py

!=

不等于

px!=py

==

等于

px==py

两个指针之间的关系运算符   表示   它们指向的地址位置之间的关系,指向  地址大的指针 大于指向地址小的指针


指针与一般整数变量之间的关系运算  没有意义。

但可以和 零0 进行  等于或不等于   的关系 运算,判断  指针  是否为空。

五、指针和数组

C语言中,数组的指针是指数组在内存中的起始地址数组元素的地址是指数组元素在内存中的起始地址。

一维数组的数组名为一维数组的指针(起始地址)

例如:
doublex[8]; //x为数组的起始地址

设指针变量px的地址值等于数组指针x(即指针变量px指向数组的首元素),

则:x[i] 、(px+i)(x+i) px[i]具有完全相同的功能:访问数组的第i+1个数组元素

int a[10], *p ;   p=a;

p[i]  <==> *(p+i)

注意:

1. 指针变量和数组在访问数组中元素时,一定条件下其使用方法具有相同的形式,因为 指针变量和数组名  都是地址量。
2. 但指针变量和数组的指针(或叫数组名)在本质上不同,指针变量是地址变量(可以++--)而数组的指针是地址常量(不可以++--)

例如:

inta[] = {1,2,3,4,5,6,7,8,9} , *p=a, i ; 数组元素地址的正确表达是:

 (A). &(a+1)   (B). a++    (C). &p   (D). &p[i]
数组名是地址常量
p++ ,p--             (对)
a++, a--             (错)
a+1 ,*(a+2) (对)

可以通过以下代码理解学习

#include <stdio.h>
#include <stdlib.h>
int main(void)
 {
 	int a[] = {1,2,3,4,5,6,7,8,9,10};
 	
 	int *p,i,n;
 	p = a;
 	
 	n = sizeof(a)/sizeof(int);
 	for(i = 0;i<n;i++)
 	{
	 printf("%d %d\n",a[i],*(p+i));	
	}
 	
 	
 	printf("\n");
 	return 0;
}

可以通过以下代码理解学习

#include <stdio.h>
 main(void)
 {
 	int a[5]={5,6,7,8,9},sum=0,i;
 	int* p = a;
 	for (i=0;i<5;i++)
 	sum += *(p+i);
 	printf("%d\n",sum);
}

题目:数组反序存放

#include <stdio.h>
#include <stdlib.h>
int main(void)
 {
 	int a[] = {1,2,3,4,5,6,7,8,9,10};
 	
 	int *p1,*p2,n,t;  //t 是临时存放量
 	
 	n = sizeof(a)/sizeof(int); //取个数
 	
 	p1 = a;  //数组头
 	p2 = &a[n-1];  //数组尾
 	
 	while(p1 < p2)
 	{
	 t = *p1;
	 *p1 = *p2;
	 *p2 = t;
	 
	 p1++;
	 p2--;	
	}
	for(t=0;t<n;t++)
	{
		printf("%d  \n",a[t]);		
	}
 	return 0;
}

六、指针和二维数组

多维数组就是具有  两个或两个以上下标的数组

C语言中,二维数组的元素连续存储,按行优先存

题目:一级指针遍历二维数组

可以通过以下代码理解学习 [有个小失误]

#include <stdio.h>
#include <stdlib.h>
int main(void)
 {
 	int a[3][2] = {{1,2},{3,4},{5,6}};
 	
 	int *p1,n,i;  
 	
 	n = sizeof(a)/sizeof(int); //取个数
 	
 	p1 = a[0];  
 
	printf("%p %p  \n",a,a+1);		
	printf("%p %p  \n",p1,p1+1);	
		
	for(i=0;i<n;i++)
	{
		printf("%d  \n",*(p1+i));		
	}
 	return 0;
}

可以把二维数组看作由多个一维数组组成。

比如ina a[3][3] ,含有三个元素,a[0],a[1],a[2] 元素a[0],a[1],a[2]都是一维数组名

二维数组名 代表数组的起始地址,数组名加1,是移动一行元素。因此,二维数组名常被 称为行地址。

行指针(数组指针)

存储行地址的指针变量,叫做 行指针变量,形式如下:

<存储类型> <数据类型>   *<指针变量名>) 表达式n };例如:

inta[2][3] ;   int  (*p)[3];

方括号中的常量表达式    表示指针加1,移动几个数据。

当用  行指针  操作  二维数组时,表达式一般写成  1行的元素个数,即列数

题目:使用行指针表示二维数组的某个元素

可以通过以下代码理解学习

//使用行指针表示二维数组的某个元素
#include <stdio.h>
#include <stdlib.h>
int main()
 {
 	int a[3][2] = {{1,2},{3,4},{5,6}};
 	int (*p)[2],i,j;  
 	
 	p =a;  
 
	printf("%p %p  \n",a,a+1);		
	printf("%p %p  \n",p,p+1);	
	//printf("%d %d %d %d\n",a[1][1],p[1][1],*(*(a+1)+1),*(*(p+1)+1));

 for(i=0;i<3;i++)
 {
 	for(j=0;j<2;j++)
 	{
	 printf("%d %d %d %d\n",a[i][j],p[i][j],*(*(a+i)+j),*(*(p+i)+j));		
	}
	printf(" \n");
 	
 }
 
 return 0;
}

七、字符指针和字符串

C语言通过使用 字符数组 来处理字符串

通常,我们把char数据类型的指针变量称为 字符指针变量

字符指针变量与字符有着 密切关系,他也被用来 处理字符串。

初始化字符指针 是把 内存中字符串的首地址 赋予指针,并不是把 该字符串复制到指针中。

charstr[] ="Hello World"; 
char*p=str;

可以通过以下代码理解学习 

//初始化字符指针 是把 内存中字符串的首地址 赋予指针,并不是把 该字符串复制到指针中。
#include <stdio.h>
#include <stdlib.h>
#include <ctype.h>
int main()
 {
 	char ch1[] = "hello world";
 	char ch2[] = "hello world";
 	char *p;
 	
 	p = ch1;  
 
    if(isalpha(*p))
    {
		if(isupper(*p))
		{
			*p = tolower(*p);
		}
		else
		{
			*p = toupper(*p);
		}		
	}
	printf("%s %p  \n",p,&p);		
	printf("%s %p  \n",ch1,ch1);
	
	p = ch2;	
    printf("%s %p  \n",ch2,ch2);

    return 0;
}

在C语言编程中,当一个字符指针  指向一个字符串常量时,不能修改指针指向的对象的值

char*p="Hello World";
*p='h';

题目:不使用任何 字符串函数,实现字符串函数连接功能

可以通过以下代码理解学习

//题目:不使用任何 字符串函数,实现字符串函数连接功能
#include <stdio.h>
#include <stdlib.h>

int main()
 {
 	char ch[100] = "Welcome";
 	char *p = " hello world",*a;
 	
 	int i = 0;
 	a = p;
 	
 	while(*(ch+i) |= '\0')  //找到字符串结束的位置
	{
	i++;
	}
	
 	while(*p != '\0') //不等于结束符的时候
    {
   	*(ch+i) = *p;
   	
   	p++;
   	i++;
   	}
   	
   	*(ch+i) = *p;  //加上字符串结束符,完成拼接的功能
   	p = a;
	puts(ch);
	puts(p);
   
    return 0;
}

八、指针数组

所谓 指针数组 是指由  若干个具有相同存储类型和数据类型的指针变量构成的集合

指针数组的一般说明形式:
         <存储类型 > <数据类型>   *<指针数组名>   [<大小>]   

指针数组名  表示  该指针数组的起始地址  声明一个指针数组

double*pa2[2] , a[2][3];

可以存放在静态存储区的 (1.全局变量 2.static局部变量 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]的第一个元素,而pa[1]指向了一维数组a[1]的第一个元素。   

题目:使用指针数组处理二维数组,求出二维数组所有元素的和。

可以通过以下代码理解学习

//题目:使用指针数组处理二维数组,求出二维数组所有元素的和。
#include <stdio.h>
#include <stdlib.h>

int main()
 {
 	int *p[2];
 	int a[2][3] = {{1,3,5},{2,4,6}};
 	int i,j,sum;
 
    p[0] = a[0];
    p[1] = a[1]; 
 	
   	for(i=0;i<2;i++)
   	{
	   	for(j=0;j<3;j++)
	   	{
		printf("%d \n",*(p[i]+j));
		sum = sum + *(p[i]+j);
		   	
		}
	  printf("\n"); 	
	}
   	
    printf("%d \n",sum);
   return 0;
}

九、多级指针

多级指针的定义:把一个指向指针变量的指针变量,称为指针变量

对于指向处理数据的指针变量称为一级指针变量,简称一级指针。

而把指向一级指针变量的指针变量称为二级指针变量,简称二级指针。

二级指针变量的说明形式如下:

    <存储类型> <数据类型>  **<指针名>


多级指针的运算
    1. 指针变量+1,是向地址大的方向移动一个目标数据。同理,多级指针运算也是以其目                标变量为单位进行偏移
    比如, int*   *p;  p+1 移动一个int * 变量所占的内存空间。

可以通过以下代码学习理解

//多级指针
#include <stdio.h>
#include <stdlib.h>

int main()
 {
 	int m = 10;
 	int *p;
 	int* *q;
 
    p = &m;
    q = &p;
    
    printf("%p %p \n",p,&m);
    printf("%p %p \n",q,q+1);
   return 0;
}

多级指针和指针数组

指针数组也可也用另外一个指针来处理。

例如: 有一个    一维字符指针数组 ps[5]

char*ps[5]  = {"Beijing","Fuzhou","Xiamen","XiAn","ShangHai"};

可以通过以下代码理解学习

//多级指针和指针数组
#include <stdio.h>
#include <stdlib.h>

int main()
 {
 
 	char *p[3]={"beijing","xiamen","duzhou"};
 	int n,i;  //i 用于循环
 	char* *q;
 
    n = sizeof(p) / sizeof(char*);//n 取个数
   
    q = p;
    
    while(i<n)
    {
		printf("%s %s \n",p[i],*(q+i));
		i++;	
	}
   // printf("%d \n",n);
    //printf("%s %s \n",p[0],*q);
    
   return 0;
}

十、void指针

void指针是一种 不确定数据类型 的指针变量,它可以通过  强转类型转换  让该变量指向任何数据类型的变量。
一般形式为: void   *<指针变量名称>


对于void指针,在 没有 强制转换类型之前,不能 进行 任何指针的算术运算。

强制转换类型   可以通过以下代码理解学习

//强制转换
#include <stdio.h>
#include <stdlib.h>

int main()
 {
 	int a = 10; 

    void *p;
    
    p = &a;
    
    printf("%d %d \n",a,*(int *)p);  //(int *)强制转换
  
   return 0;
}

 题目:使用void指针遍历一维数组 

可以通过以下代码理解学习

//题目:使用void指针遍历一维数组
#include <stdio.h>
#include <stdlib.h>

int main()
 {
 	int a[5] ={1,2,3,4,5}; 
    int n,i,*q;
    void *p;
    p = a;
    q = (int *)p;
    n = sizeof(a) / sizeof(int*);//n 取个数
     
    for(i = 0;i<n;i++)
    {
	 printf("%d     ",a[i]);	
	 printf("%d     ",*((int *)p+i));
	printf("%d\n",*(q+i));
	}
   return 0;
}

十一、const修饰指针 (重难点)

常量化变量 的值

一般说明形式如下:

const<数据类型>变量名=[<表达式>];

常量化变量 是 为了使得变量的值不能修改

变量有 const修饰时,若 想用指针间接访问变量,指针 也要有 const修饰。     

const放在指针声明什么位置呢?

回答:开头

常量化指针  目标表达式
一般说明形式如下:

const<数据类型>  * <指针变量名称 [=<指针运算表达式>]

常量化指针目标  限制 通过 指针改变其目标的数值但是指针变量存储的地址可以修改

可以通过以下代码理解学习

常量化指针 变量  及其  目标表达式

一般说明形式如下:

const<数据类型>    *   const<指针变量名>   =   <指针运算表达式>

常量化指针目标  是  限制 通过 指针改变其目标的数值 但是<指针变量>存储的地址值可以修改

常量化指针变量

一般说明形式

<数据类型>   *   const<指针变量名称>  [<指针运算表达式>]

使得<指针变量>存储的地址值不能修改。但可以通过 *<指针变量名称>可以修改所指向变量的数值。

可以通过以下代码理解学习


总结

指针:~用法、概念、含义、运算、指针和数组、指针和二维数组、字符指针和字符串、指针数组、多级指针、void指针、const修饰指针

大家可以通过代码理解学习

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值