前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >专栏 >C语言程序设计核心详解 第八章 指针超详细讲解_指针变量_二维数组指针_指向字符串指针

C语言程序设计核心详解 第八章 指针超详细讲解_指针变量_二维数组指针_指向字符串指针

原创
作者头像
小徐在进步
发布于 2024-10-04 13:38:23
发布于 2024-10-04 13:38:23
21400
代码可运行
举报
文章被收录于专栏:c语言程序设计c语言程序设计
运行总次数:0
代码可运行

第八章 指针超详细讲解指针变量二维数组指针_指向字符串指针

1.指针变量

1.1 指针变量的定义

C语言有两种变量:

1.变量(普通变量)存储内容值;

2.地址变量(指针变量)存储地址值;

定义的格式:

类型名 指针变量名

如:

int a,b,p1,p2;

float x,y,p3,p4;

char s,p5,p6;

注:

(1) 定义变量(普通变量,指针变量)都必须在前面有类型名。

(2)在定义指针变量时,指针变量名前的*表示现定义的是一个指针类型的变量。星号并不是指针变量名的一部分,只是一个标志

用户变量名是_,数字字母组成的,不能用*开头

但是指针变量是*开头,说明我们要定义的是指针变量

(3) 指针变量专门用来存地址,禁止将一个整型值直接赋给一个指针变量。

代码语言:c
代码运行次数:0
运行
AI代码解释
复制
int a,b,*p;
a=1000;
b=2000;
p=4000;  //非法

1.2 指针变量的引用

"&"取地址运算符,通过&运算可以取出普通变量的地址。

“*”指针运算符,、*可以取出指针变量所指向的普通变量的值,(间接引用普通量)

例子:

代码语言:c
代码运行次数:0
运行
AI代码解释
复制
*指针变量名
如:
int a,b=20,c=30;
int d=40,*p;
p=&d;
a=*p;
a=d;

重点补充:画图做指针相关题目:

在c语言的题目中,关于,数组,static,指针,链表,文件操作,我们要画图,来保证正确

上面的例子可以画图表示为,指针画箭头指向,普通变量放入小房子

本小节注意:

(1)可以通过赋值使一个指针变量“指向”某一普通变量(指针变量=&普通变量)

例如:

代码语言:c
代码运行次数:0
运行
AI代码解释
复制
int a=10;
int *p;
p=&a

(2)在C语言中正确的做法是先让指针变量指向一个确定的存储单元后,再通过该指针变量引用它所指向的存储单元。

例如:

代码语言:c
代码运行次数:0
运行
AI代码解释
复制
int *p;
*p=200; 危险!!!

从形式上来说虽然没错,但是如果不给指针变量初始化,指针变量随机拿地址的话,可能会拿到系统区的地址,修改系统区的值,就会让操作系统紊乱所以不合法

(3)变量名(普通变量,指针变量)都表示其存储单元内的值。

p~1~=p~2~; // p~1~指向了p~2~所指向的单元。

(4)若指针变量p指向变量a,即将变量a的地址赋给了指针变量p。

代码语言:c
代码运行次数:0
运行
AI代码解释
复制
:int a=20,*p=&a;
则有下列结果:
1. *p是a
2. p是&a
3. &*p是&a是p
4. *&a是*p是a
5. (*p)++是a++
6. (*p)--是a--
7. ++(*p)++a ++*p
8. --(*p)--a --*p

(5)所有的指针变量在内存中分配的字节数相同。sizeof() 2字节

例题:

1.请输出下列程序的结果

代码语言:c
代码运行次数:0
运行
AI代码解释
复制
void fun(int *x,int *y)
{
	printf("%d %d",*x,*y);
	*x=3;
	*y=4;
}
main()
{
	int x=1,y=2;
	fun(&y,&x);
	printf("%d %d ",x,y);
}

结果如下:

2 1 4 3

注意形参,实参

2.请输出下列程序的结果

代码语言:c
代码运行次数:0
运行
AI代码解释
复制
#include<stdio.h>
void swap(int *p1,int *p2)
{
	int temp;
	temp=*p1;
	*p1=*p2;
	*p2=temp;
}

main()
{
	int a,b;
	int *p1=&a,*p2=&b;
	scanf("%d%d",p1,p2);
	swap(p1,p2);
	printf("%d,%d",*p1,*p2);
}

假设输入 2 5

画图解决:

输出:5 2

3.请输出下列程序的结果

代码语言:c
代码运行次数:0
运行
AI代码解释
复制
#include<stdio.h>
void swap(int *p1,int *p2)
{
	int *temp;
	temp=p1;
	p1=p2;
	p2=temp;
}

main()
{
	int a,b;
	int *p1=&a,*p2=&b;
	scanf("%d%d",p1,p2);
	swap(p1,p2);
	printf("%d,%d",*p1,*p2);
}

输出:2 5

4.请输出下列程序的结果

代码语言:c
代码运行次数:0
运行
AI代码解释
复制
#include<stdio.h>
void swap(int *p1,int *p2)
{
	int *temp;
	*temp=*p1;
	*p1=*p2;
	*p2=*temp;
}

main()
{
	int a,b;
	int *p1=&a,*p2=&b;
	scanf("%d%d",p1,p2);
	swap(p1,p2);
	printf("%d,%d",*p1,*p2);
}

实际不合法,函数中的指针变量,没有初始化,可能会随机指向系统区,让计算机崩溃

2.指向数组的指针变量

若数组做为形参,则将数组名做指针变量来处理。

指向数组元素的指针变量:

由于数组元素与普通一样,所以定义指向数组元素的指针变量与定义指向普通变量的指针变量完全一样。

2.1 指向一维数组的指针变量

注:

(1)在c语言中规定:数组名代表数组的首地址,而且是一个==地址常量==

(2)当指针变量指向数组中的某一个元素时,指针变量+1后指向数组的下一个元素,指针变量减1时指向数组中前一个元素。

(3)当指针变量指向数组时,下标运算([])用于数组也可用于指针变量后

:one:*(p+I) *(a+i) ai pi

:two: p++ *(p++) ++的优先级高于

:three:(p)++ ++(p)

代码语言:c
代码运行次数:0
运行
AI代码解释
复制
例子1:
若有定义:int b[5]={10,30,20,15,40};
int *q=b+2; //q最开始指向20

则:
*q++   表达式的值?,同时q指向了?   20 b[3]
*++q   表达式的值?,同时q指向了?   15 b[3]
(*q)++ 表达式的值?,同时q指向了?   20 b[2]
++(*q) 表达式的值?,同时q指向了?   21 b[2]

例子2:

代码语言:c
代码运行次数:0
运行
AI代码解释
复制
举例指针在数组中的使用
main()
{
int *p,a[3],I;
p=a;
for(i=0;i<3;i++)
{
	scanf("%d",p++);
}
printf("\n\n");
for(p=&a[0];p<a+3; )
	printf("%d ",*p++);

(4)若两个指针变量指向同一个数组,则这两个指针变量可以进行大小比较如:

char s10;

char p=s+3,p2=&s7;

可以做差,等到的两个数组的距离差

(5)在形参中的数组实际上是一个指针变量,并不是真正的数组,因为该"数组名"的值是可以改变的,而真正的数组名的值是不能改变的。

(6)若形参是数组或指针变量,则在函数中可以通过该形参改变实参的值

2.2 指向二维数组的指针变量(难)

二维数组的指针分为两类,一类是列地址(列指针),一类是行地址(行指针),列地址控制的是具体的行列,行地址一次控制一整行,移动是行移动。

若a是一个二维数组,则有:

(1)a+i是行指针,即指向的是一整行,若对它加1则指向下一行。==说的是行指针==

(2)*(a+i)和ai一样,都是一个列指针即指向的是一个元素 ==说的是列指针==

(3)*(a+i)+j和ai+j一样,都表示元素aI的地址。即与&ai等价

*(a+i)+j ,ai+j, &ai ==说的是元素aI的地址,3种地址表示==

(4)*(*a+i)+j),*(aI+j),(*(a+i))j和ai一样,都表示元素ai

小技巧:

二维数组的引用,肯定存在一个*一个[]或或两个*,不能出现只有一个的情况

int (*)3 是行指针的类型,int *是列指针的类型

例如:

int w2,则对w数组元素非法引用是

A. *(w0+2) ==第一行第三个元素的值==

B. *(w+1)2 ==越界不合法==

C. w0

D. *(w1+2)

E. w1+2 ==秒杀不合法==

2.2.1 int *p类型

如:

代码语言:c
代码运行次数:0
运行
AI代码解释
复制
int a[3][4];
int *p=&a[0][3];

则:
p+1指向元素a[1][0];
p+4指向元素a[1][3];
p-2 指向元素a[0][1];
常用于取二维数组a元素地址的方式:
&a[i][j],a[i]+j,*(a+i)+j

2.2.2 int (*p)m类型

行指针,一次加减指向一行

如:

代码语言:c
代码运行次数:0
运行
AI代码解释
复制
int a[5][7];
int (*p)[7];
p=a;

char b[10][80];
char (*r)[80];
r=b+5;
代码语言:c
代码运行次数:0
运行
AI代码解释
复制
main()
{
	int a[3][4]={1,2,3,4,5,6,7,8,9,10,11,12};
	int (*p)[4];
	p=a;
	for(i=0;i<3;i++)
	{
		for(j=0;j<4;j++)
			printf("%d",p[i][j]);
		printf("\n");
	}
}
代码语言:c
代码运行次数:0
运行
AI代码解释
复制
int a[3][4]={{1,2,3},{4,5,0},(*pa)[3];
int i;
pa=a;
for(i=0;i<3;i++)
	if(i<2)pa[1][i]=pa[1][i]-1;
	else pa[1][i]=1;
	printf("%d\n",a[0][1]+a[1][1]+a[1][2]);

输出7

3.指向字符串的指针变量

字符串常量:C语言对字符串常量是按首地址处理字符串常量

意味着双引号“”要当作地址!!!

给出几个例子,初始指向字符串的指针变量

(1)char str[]="china"; ==正确,字符串数组的初始化==

(2)char *p="china"; ==正确,指针变量后接一个地址“”==

(3)str="Chinese" ; ==错误,str为字符串常量,不能这么修改==

(4)p=“Chinese”;==正确,指针变量修改指向Chinese==

(5)char *p ={"china"};==错误,指针后面要加地址,如果是花括号就识别不出来了,以为是初始化,必须是双引号==

(6)char str[]={"china"};==正确,花括号可以省略==

(7)char p;p="china";==错误,字符串常量不能修改==

例子:

代码语言:c
代码运行次数:0
运行
AI代码解释
复制
# include<stdio.h>
# include<string.h>
int main()
{
    char s[20]="abcdefGHI";
    char p[20]="1234567";
    printf("%s\n",s+2); //cdefGHI
    printf("%s\n",p+5); //67
    printf("%d\n",strlen(p+2));//5
    printf("%s\n",strcpy(p+3,s+3));//defGHI 从p+3开始,p+3是当前地址
    printf("%s\n",p);    //123defGHI
}

4.指向函数的指针变量

函数名与数组名一样,是起始地址,而且是一个地址变量。

定义指向函数的指针变量的方式

类型名 (*指针变量名) () ;

来看一个具体的实例:

代码语言:c
代码运行次数:0
运行
AI代码解释
复制
int min(int a,int b)
{
	return a>b?b:a;
}
int max(int a,int b)
{
	return a>b?a:b;
}
int main()
{
	int x=6,y=10;
	int (*p)();
	p=max;
	printf("%d",max(x,y));
	printf("%d",p(x,y));
	p=min;
	printf("%d",min(x,y));
	printf("%d",p(x,y));
}

5.指针数组和指向指针的指针变量

5.1 指针数组

若一个数组的所有元素均为指针类型(地址),则称为指针数组。

格式:

类型名 *数组名常量表达式

int *s10;

其实就是10个 int *s类型

与二维数组行指针形式辨析 int (*p)10; 多个括号。

例子:

代码语言:c
代码运行次数:0
运行
AI代码解释
复制
# include<stdio.h>
# include<string.h>
int main()
{
    char ch[3][4]={"123","456","78"},*p[3];
    int i;
    for(int i=0;i<3;i++)
    {
        p[i]=ch[i];
    }
    for(i=0;i<3;i++)
    {
        printf("%s",p[i]);
    }
}

输出结果:12345678

5.2 指向指针的指针变量

用来存放指针变量地址的指针变量称为指向指针的指针变量。

定义格式:

基类型名 **指针变量名

例如:

代码语言:c
代码运行次数:0
运行
AI代码解释
复制
int a=3;
int *p=&a;
int **k=&p;
则,*k得到变量p(变量a的地址)
**k得到变量a的值(a的数据3

6.空指针

指针变量可以有空值,即指针变量不指向任何变量,不指向任何有用的存储单元

在系统中已将NULL定义为0,即NULL的值为0.

int a,b,c,*p=NULL;

此时p的值为空指针,即p不指向任何有用的存储单元。尽管NULL的值为0,但我们不能认为p指向了地址为0的存储单元。

注:

(1)当一个指针变量的值为空指针时,我们不能引用它所指向的存储单元。

(2)若某指针(地址)的基类型为void型,则有引用时应进行相应的强制类型置换。

看一个非法的例子:

代码语言:c
代码运行次数:0
运行
AI代码解释
复制
//错误例子,编译错误,原因是null没有房子
int main()
{
	int a[]={1,2,3,4,5,6,7,8,9,10,11,12};
	int *p=a+5,*q=NULL;
	*q=*(p+5)printf("%d %d\n",*p,*q);
}

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

评论
登录后参与评论
暂无评论
推荐阅读
编辑精选文章
换一批
开讲啦:Chap 08 善于利用指针
如果在程序中定义了一个变量,在对程序进行编译时,系统就会给这个变量分配内存单元,编译系统根据程序中定义的变量类型,分配一定长度的空间,内存区的每一个字节有一个编号,这就是地址,它相当于旅馆中的房间号,在地址所标志的内存单元中存放的数据则相当于旅馆房间中居住的旅客。我们将地址形象化为指针,即通过它能找到以它为地址的内存单元。
石璞东
2021/10/13
5080
C语言字符串与指针-学习二十五
本文最后更新于2022年02月20日,已超过7天没有更新。如果文章内容或图片资源失效,请留言反馈,我会及时处理,谢谢!
XG.孤梦
2022/03/01
2650
C语言字符串与指针-学习二十五
C语言入门系列之8.指针的概念与应用
指针是C语言中的一个重要的概念,也是C语言的一个重要特色。 正确而灵活地运用它,可以有效地表示复杂的数据结构;能动态分配内存;能方便地使用字符串;有效而方便地使用数组等。 掌握指针的应用,可以使程序简洁、紧凑、高效。可以说,不掌握指针就是没有掌握C的精华。
cutercorley
2020/07/23
1.4K0
C语言入门系列之8.指针的概念与应用
指针详解(二级指针、指针数组和数组指针、字符指针、二维数组传参、函数指针变量)(二)
走在努力路上的自己
2024/01/26
7370
指针详解(二级指针、指针数组和数组指针、字符指针、二维数组传参、函数指针变量)(二)
关于指针数组与数组指针详解(知识点全面)
它是一个数组,数组的元素都是指针,数组占多少个字节由数组本身的大小决定,每个元素都是一个指针。
利刃大大
2023/04/12
3470
关于指针数组与数组指针详解(知识点全面)
C二维数组指针
二维数组在概念上是二维的,有行和列,但在内存中所有的数组元素都是连续排列的,它们之间没有“缝隙”。以下面的二维数组 a 为例:
随心助手
2021/03/04
1.1K0
C二维数组指针
【C 语言】指针 与 数组 ( 指针 | 数组 | 指针运算 | 数组访问方式 | 字符串 | 指针数组 | 数组指针 | 多维数组 | 多维指针 | 数组参数 | 函数指针 | 复杂指针解读)
数组名称不作为常量指针的场合 : 数组名类似于常量, 但不是常量, 下面两种场合数组名与常量指针不同 ;
韩曙亮
2023/03/27
3.9K0
【C 语言】指针 与 数组 ( 指针 | 数组 | 指针运算 | 数组访问方式 | 字符串 | 指针数组 | 数组指针 | 多维数组 | 多维指针 | 数组参数 | 函数指针 | 复杂指针解读)
二维数组和指针_二维数组与指针
二维数组和指针⑴ 用指针表示二维数组元素。 要用指针处理二维数组,首先要解决从存储的角度对二维数组的认识问题。我们知道,一个二维数组在计算机中存储时,是按照先行后列的顺序依次存储的,当把每一行看作一个整体,即视为一个大的数组元素时,这个存储的二维数组也就变成了一个一维数组了。而每个大数组元素对应二维数组的一行,我们就称之为行数组元素,显然每个行数组元素都是一个一维数组
全栈程序员站长
2022/11/17
1.6K0
c语言从入门到实战——数组指针与函数指针
数组指针和函数指针是C语言中的两种重要指针类型。数组指针指向一个数组,可以用来访问和修改数组中的元素;而函数指针则指向一个函数,可以用来调用该函数。两者在语法和用法上有所不同,需要仔细区分。正确理解和使用它们可以提高程序的效率和可维护性。
鲜于言悠
2024/03/20
1780
c语言从入门到实战——数组指针与函数指针
10分钟,掌握C语言指针
说到指针,估计还是有很多小伙伴都还是云里雾里的,有点“知其然,而不知其所以然”。但是,不得不说,学了指针,C语言才能算是入门了。指针是C语言的「精华」,可以说,对对指针的掌握程度,「直接决定」了你C语言的编程能力。
刘盼
2020/11/03
1.5K0
10分钟,掌握C语言指针
【进阶指针一】字符数组&数组指针&指针数组
目录 1.初阶指针内容回顾 2.字符指针 2-1 字符指针长什么样? 2-2 误区: 2-3  代码一和代码二的异同: 2-4 关于字符常量区: 2-5 一道为了区分栈区和字符常量区&&字符数组和字符指针的面试题:  3.指针数组 3-1 指针数组长什么样捏? 3-2 初级使用(或者说给你看一下基本使用): 3-3这才是指针数组的正确使用方法!【指针数组模拟打印二维数组】  4. 数组指针 4-1 区分取地址数组名和数组名(老生常谈了) 4-2 辨析数组指针和指针数组  4-3 学会了?来看一个小测试
MicroFrank
2023/01/16
1K0
C语言——指针(2)
前面我们已经了解了指针的基本概念以及简单的使用,那么什么问题一定要使用指针解决呢?
用户11352420
2024/11/07
1860
C语言——指针(2)
[C语言]初阶指针和结构体
内存:内部存储器,暂存程序/数据——掉电丢失 SRAM,DRAM,DDR,DDR2,DDR3。
IT编程爱好者
2023/04/12
5360
[C语言]初阶指针和结构体
【C语言】指针进阶:字符指针&&数组指针&&函数指针
✨作者:@平凡的人1 ✨专栏:《C语言从0到1》 ✨一句话:凡是过往,皆为序章 ✨说明: 过去无可挽回, 未来可以改变 ---- 🌹感谢您的点赞与关注,同时欢迎各位有空来访我的🍁平凡舍 ---- 文章目录 @[toc] 🚀前言 🚀字符指针 🚀指针数组 🚀数组指针 🍁&数组名 与 数组名 🍁数组指针的使用 🚀数组传参、指针参数 🍁一维数组传参 🍁二维数组传参 🍁一级指针传参 🍁二级指针传参 🚀函数指针 🚀结语 🚀前言 回想之前,我们学了指针的一些基础👉 指针与结构体 我们知道了指针的概念
平凡的人1
2022/11/15
3.3K0
【C语言】指针进阶:字符指针&&数组指针&&函数指针
C语言之指针详解(3)
上述的代码const char* pstr = "hello bit.";特别容易让大家以为是把字符串hello bit.放到字符指针pstr里了,但是本质是把字符串hello bit.首字符的地址放到了pstr中。所以说,上面的代码是把常量字符串的首字符h的地址放到指针变量pstr中。
Crossoads
2024/10/21
870
C语言之指针详解(3)
C/CPP 指针变量 | 数组指针 | 指针数组 | 野指针 | 空指针
普通变量可以不赋初值,但是指针变量的初值必须万分慎重,因为未来的*操纵会以这个初值为目标内存地址,往里面读写数据(可以才C primer plus中看到相应分析)
CtrlX
2022/10/04
1.8K0
C/CPP 指针变量 | 数组指针 | 指针数组 | 野指针 | 空指针
C 二维数组和指针、函数指针、typedef等的一些笔记
&arr是指整个数组的首地址,而arr是指数组首元素的首地址,虽然所表示的意义不同,但二者之间的值却是相同的。
小锋学长生活大爆炸
2022/03/29
6790
C 二维数组和指针、函数指针、typedef等的一些笔记
C和指针小结(C/C++程序设计)
C和指针 相关基础知识:内存的分配(谭浩强版) 1、整型变量的地址与浮点型/字符型变量的地址区别?(整型变量/浮点型变量的区别是什么) 2、int *p,指向整型数据的指针变量。 3、通过指针变量访问整型变量。 4、*p :指针变量p指向的存储单元(变量) 5、p = &a——>> *p = *&a 6、用指针作函数参数 7、调用函数中,由于虚实结合是采用单向的“值传递”方式,只能从实参向形参传数据,形参值的改变无法回传给实参。 8、引用一个数组元素可以用(1)下标法(2)指针法(占内存小,运行速度快) 9
互联网金融打杂
2018/04/03
6360
C和指针小结(C/C++程序设计)
c语言指针与数组的深入理解
引言:本篇再一次写到指针,学过c语言的都知道,指针是初学c语言时候遇到的一个比较难搞的知识点。你尽管可以想的简单,但是其实如果去用的话,没有一个更加深入的理解,那么后续的学习到数据结构就会艰难无比。
兰舟千帆
2022/07/16
5460
c语言指针与数组的深入理解
C语言之指针变量
  4、指向常量的常量指针:有2个const修改,既不能间接修改变量的值,也不可重新赋值新变量地址
tandaxia
2018/09/27
2.2K0
推荐阅读
相关推荐
开讲啦:Chap 08 善于利用指针
更多 >
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档
本文部分代码块支持一键运行,欢迎体验
本文部分代码块支持一键运行,欢迎体验