指针进阶详解(上)

指针进阶之详解指针 目录 文章目录 前言 一、sizeof与strlen里的指针 二、指针题目详解 前言 指针作为c语言里的重要知识点与难点,令很多同学困扰。本篇博客将以另一种角度出发,带你更加理解指针,希望一些基础比较薄弱的同学能在本篇博客中有所收获。 我们首先要明确,数组名代表的是首元素地址,但它有两个例外。 1.当数组名单独出现在sizeof内部时,它代表的是整个数组的地址,此时sizeof求的的是整个数组的大小。 2.与&相结合时,它代表的是整个数组的地... 阅读详情

前言

指针是检验学者对C语言掌握好与坏的重要标准之一,在指针初阶中,我们以及详细介绍了以下内容:

  1. 指针是一个变量,用来存放地址,地址唯一标识一块空间。
  2. 指针的大小固定为4/8个字节(32位平台/64位平台)
  3. 指针是有类型,指针的类型决定了指针±整数的步长,指针解引用时候的权限。
  4. 指针的运算。

接下来,我们将继续探讨指针的高级主题。

1. 字符指针

在指针的类型中我们知道有一种指针类型位字符指针 char*
一般用法:

int main()
{
	char ch = 'w';
	char* pc = &ch;
	*pc = 'a';
	return 0;
}

还有一种使用方法:

int main()
{
	const char* pstr = "hello world";
	printf("%s\n", pstr);
	return 0;

  • 代码const char* pstr = "hello world"特别容易让初学者以为把字符串 hello world放到字符指针pstr里,但本质上是把字符串 hello world的首字符的地址放到了pstr中。

1.1 相关面试题

题目:

int main()
{
	char str1[] = "hello world";
	char str2[] = "hello world";
	const char *str3 = "hello world";
	const char *str4 = "hello world";

	if (str1 == str2)
		printf("str1 and str2 are same\n");
	else
		printf("str1 and str2 are not same\n");

	if (str3 == str4)
		printf("str3 and str4 are same\n");
	else
		printf("str3 and atr4 are not same\n");
	return 0;
}

运行结果:
在这里插入图片描述
代码解读:

**这里str3和str4指向的是同一个常量字符串。C/C++会把常量字符串存储到单独的一个内存区域,当几个指针指向同一个字符串的时候,实际上他们会指向同一块内存。
但是用相同的常量字符串去初始化不同的数组时会开辟不同的内存块。
所以str1和str2不同;str3和str4相同。

2. 指针数组

在指针初阶中我们已经介绍了指针数组,指针数组是一个存放指针的数组。
在这里我们在简单复习一下,下面数组是什么意思?

int* p1[10];  //整型指针的数组
char *arr2[4];//一维字符指针的数组
char** arr3[5]; //二级字符指针的数组

3. 数组指针

3.1 数组指针的定义

首先说明数组指针是指针。
我们已经熟悉:
整型指针:int * pint; 能够指向整型数据的指针。
浮点数指针:float * pf; 能够指向浮点型数据的指针。
那么数组指针应该是:能过指向数组的指针。

下面代码那个是数组指针?

int* p1[10];
int(*p2)[10];
  • 要明白上面两个类型其实很简单,一个类型里会出现很多运算符,他们也像普通的表达式一样,有优先级,其优先级和运算优先级一样,所以我总结了一下其原则:从变量名处起,根据运算符优先级结合,一步一步分析.(字符串优先级博客链接)

解读:

int* p1[10];
//解释:从p1开始,由于[]的优先级高于*,p1先后[]结合,所以p1是一个数组。
//		然后在与*结合,说明数组中的元素是指针类型;在和int结合说明指针所指向的内容的类型是指针类型
//		所以p1是由一个返回整型数据的指针所组成的数组(p1为指针数组)

int(*p2)[10];
//解释:由于()的优先级高于[]。所以从p2开始,先和*结合说明p2是一个指针。
//		在和[]结合,说明指针所指向的内容是一个数组;在和int结合,说明数组中的每一个元素是整型类型
//		所以p2是指向一个由整型数据组成的数组的指针。(p2是一个数组指针)

3.2 &数组名VS数组名

对于下面的数组:

int arr[10];

arr和&arr分别是什啥?
我们知道arr是数组名,数组名表示首元素地址。那&arr数组名到底是什么呢?
我们先来看下面几段代码:

代码一:

int main()
{
	int arr[10] = { 0 };
	printf("%p\n", arr);
	printf("%p\n", &arr);
	return 0;
}

运行结果:
在这里插入图片描述
在上面这段代码中,数组名和&数组名打印的地址是一样的。
难道两个真是一样的吗?
我们再来看下面这段代码:

代码一:

int main()
{
	int arr[10] = { 0 };
	printf("arr=%p\n", arr);
	printf("&arr=%p\n", &arr);

	printf("arr+1=%p\n", arr + 1);
	printf("&arr+1=%p\n", &arr + 1);
	return 0;
}

运行结果:
在这里插入图片描述

对比上面两端代码我们发现虽然arr和&arr值是一样的,但意义不同。

实际上:&arr 表示的是数组的地址,而不是数组首元素的地址。
本例中 &arr 的类型是:int (*)[10],是一种数组指针类型。
数组的指针+1,跳过整个数组的大小,所以 &arr 相对于 arr 的差值为40。

3.3 数组指针的使用

介绍完数组指针,那数组指针如何使用呢?
既然数组指针指向的是数组,那数组指针中存放的应该就是数组的地址。

一个数组指针的使用:

//void print_arr(int arr[3][5], int row, int col)
void print_arr(int (*arr)[5], int row, int col)
{
	for (int i = 0; i < row; i++)
	{
		for (int j = 0; j < col; j++)
		{
			printf("%d ", arr[i][j]);
		}
		printf("\n");
	}
}

int main()
{
	int arr[3][5] = { {1,2,3,4,5},{6,7,8,9,10},{11,12,13} };
	print_arr(arr, 3, 5);
	//数组名arr,表示首元素地址
	//但二维数组的首元素是二维数组的第一行
	//所以这里传递的arr,其实相当于第一行的地址,是一维数组的地址,可以使用一维数组来接受
	return 0;
}

运行结果:
在这里插入图片描述

3.4 数组和数组指针类型实例解读

学习了数组和数组指针,接下来我们来看看下面这些代码的意思:

int arr[5];
//解读:arr先和[]结合,说明arr是一个数组;在和int结合,说明数组中的元素是int类型。
//	   所以arr是由整型数据组成的数组
int *parr1[10];
//解读:parr1先和[]结合,说明pass1是一个数组;在和*结合,说明数组的元素是指针类型;最后和int结合,说明指针指向的内容的类型是整型。
//	   所以pass1是有一个返回整型数据的指针所组成的数组。
int (*parr2)[10];
//解读:parr2先和*结合,说明parr2是一个指针;在和[]结合,说明指针所指向的内容是一个数组;最后和int结合,说明数组中的元素是整型类型。
//	   所以parr2是一个指向由整型数据组成的数组的指针。
int (*parr3[10])[5];
//解读:parrr3先和先和[]结合,说明parr3是一个数组;在和*结合,说明数组的元素是指针类型;在和[]结合,说明指针指向的是一个数组;最后和int结合说明,数组中的元素类型是整型。
//	   所以parr3是一个由指向整型数组的指针组成的数组。

其他各种复杂数据类型和上面一样,根据操作符优先级一步步分析即可得到答案!!

4. 数组参数和指针参数

在写代码时,难免要把数组或指针传个函数,那么函数的参数该如何设计呢?

4.1 一维数组传参

void test(int arr[])//ok 形参写成一维数组形式,可以不用指定大小
{}
void test(int arr[10])//ok
{}
void test(int *arr)//ok
{}
void test2(int *arr2[10])//ok
{}
void test2(int** arr)//ok arr2的地址时,传的是首元素地址。而首元素的类型为int *也是一个地址。
{}                  //所以arr2传的是一个二级指针

int main()
{
	int arr[10] = { 0 };
	int* arr2[10] = { 0 };

	test(arr);
	test2(arr2);
	return 0;
}
  • 一维数组传参,形参部分可以是数组,也可以是指针。
  • 传一维数组地址其实本质上是传的是指针。虽然语法上可以写成数组形式,但这仅是C语言为方便初学者理解而设计的,俗称挂羊头卖狗肉,并不会真正带内存中开辟一块空间来存放数组,本质上还是一个指针。所以参数写成数组形式时,[ ]中不仅可以不说明大小,即使给1000也没关系。编译器在编译参数时,会把它识别为一个指针,而非数组。

4.2 二位数组传参

//参数为二维数组时,形参部分,行可以省略,列不行
void test(int arr[3][5])//ok
{}
void test(int arr[][])//error 
{}
void test(int arr[][5])//ok
{}

//二维数组传参,参数为指针时,指针为数组指针,类型为int (*)[5]
void test(int *arr)//error  
{}
void test(int *arr[5])//error
{}
void test(int (*arr)[5])//ok
{}

int main()
{
	int arr[3][5] = { 0 };
	test(arr);
	return 0;
}
  • 二维数组传参,形参部分可以是数组,也可以是指针。
  • 二维数组传参时,函数参数设计只能省略第一个[ ]中的数字。因为对于一个二维数组来说,数据在内存中时连续存放的,所以可以不知道有多少行,但必须知道每=一行有多少个元素。

4.3 一级指针传参

void print(int* p, int sz)
{
	for (int i = 0; i < sz; i++)
	{
		printf("%d ", *(p + i));
	}
}

int main()
{
	int arr[10] = { 1,2,3,4,5,6,7,8,9,10 };
	int* p = arr;
	int sz = sizeof(arr) / sizeof(arr[0]);
	print(p, sz);//一级指针p,传给函数
	return 0;
}
  • 一级指针传参时,参数只能是指针形式。

4.4 二级指针传参

void tesy(char **p)
{}

int main()
{
	char n = 10;
	char* p = &n;
	char** pp = &p;

	test(pp);
	test(&p);
	return 0;
}
  • 二级指针传参时,参数只能是指针形式。

5.结尾

本篇文章到此就结束了。创作不易,如果对你有帮助记得点赞加收藏哦!感谢您的支持!!

带有HSE组件的S32系列芯片中各子系统如何依次启动? 仔细阐述了上电后各个子系统的启动顺序,并给出了详细的启动步骤流程图。 阅读详情

相关推荐

解决usbisp不识别无法烧录Atmega328P,Arduino不识别问题

如果使用Arduino IDE里面的烧录,可能会遇到一个问题,就是不识别国产这种廉价的USBISP 点击烧录引导程序,会遭遇到找不到USB设备的问题,选哪个都会提示找不到,比如选择USBasp could not find USB device with vid=0x16c0 pid=0x5dc vendor='www.fischl.de' product='USBasp' 因此,我们需要使用到progisp这一个软件的1.72版本 选择好芯片的型号后,调用编译好的HEX文...

arenascat的博客 7436

指针进阶详解

前言 在初级指针中我们知道了一些关于指针的主题: 指针就是个变量,用来存放地址,地址唯一标识一块内存空间。 指针的大小是固定的4/8个字节(32位平台/64位平台)。 指针是有类型,指针的类型决定了指针的±整数的步长,指针解引用操作的时候的权限。 指针的运算 这个章节,我们继续探讨指针的高级主题。 字符指针 我们都知道在指针类型中我们知道一种...

java优质资源提供与创作者 2722

核磁干货 | RESTplus实战:静息态fMRI预处理全流程解析

本文详细解析了使用RESTplus工具包进行静息态fMRI数据预处理的完整流程,包括数据准备、环境配置、预处理步骤及高级分析技巧。RESTplus作为基于SPM的批处理工具,以其图形化界面和智能化参数设置显著提升了核磁静息态数据分析的效率,特别适合新手和临床研究人员。文章还分享了实战中的常见问题解决方案和性能优化技巧。

wine的专栏 880

指针进阶(详解)

有人曾说过不会指针等于没有学习c语言,而我也是非常认同这个观点的,要想学习好c语言,指针是比不可缺少的,如果指针学不会c语言也就没办法学好,而向如此越重要的东西越比较难学,但难学并不代表学不会,这片文章将由简单到复杂让你深刻的了解指针,从此不再害怕指针的学习。数组指针是指针?还是数组?答案是:指针。我们已经熟悉:整形指针: int * pint;能够指向整形数据的指针。浮点型指针: float * pf;能够指向浮点型数据的指针。那数组指针应该是:能够指向数组的指针。

m0_68662723的博客 2649

SpringBoot整合oceanbase,实现oracle无缝切换到oceanbase

随着去“IOE”化的潮流,近些年来,许多与国家相关的项目不约而同到地往”国产化“方向靠拢,不可避免地,一些项目可能需要进行数据库迁移。

4619

从理论到实践:笛卡尔空间阻抗控制的实现挑战与变体解析

本文深入探讨了笛卡尔空间阻抗控制的核心原理、工程实现中的五大挑战及经典变体实战解析。通过详细的数学建模和实际案例分析,揭示了阻抗控制在工业机器人、医疗设备等领域的应用价值,特别是在力感知精度、动力学模型校准和实时计算等方面的关键技术突破。

weixin_30952535的博客 448

【C语言进阶】指针详解

C语言中的指针是理解和使用C语言的关键部分。它们提供了对内存的直接访问能力,指针的使用可以极大地提高程序的效率和灵活性。但同时也需要谨慎使用,以避免内存泄漏、越界访问等错误。

byte轻骑兵的技术小窝 1万+

制作3D地形图的方法-使用GlobalMapper和3ds Max软件

打开GlobalMapper软件,在菜单栏中选择“文件”>“打开数据文件”,然后选择相应的高程数据文件。在菜单栏中选择“渲染”>“渲染设置”,根据需要进行设置,如分辨率和输出格式。选择地形对象,点击菜单栏中的“渲染”>“材质编辑器”,然后根据需要调整材质属性,如颜色、纹理和光照等。在菜单栏中选择“工具”>“高程栅格和网格”>“创建地形网格”。在菜单栏中选择“文件”>“导出”>“导出栅格格式”。打开3ds Max软件,在菜单栏中选择“文件”>“导入”,然后选择之前导出的地形数据文件。步骤3:导出地形网格。

JqlScala的博客 1535

不会指针?还不进来看看——进阶指针详解

指针是C语言的灵魂,不会指针,不知道指针怎么用的,进来看看。

weixin_73888239的博客 1402

Winform从入门到精通(1)——Label(史上最全)

本篇文章是对专栏《winform控件从入门到精通》的详细介绍

qq_34059233的博客 4万+

【HYSPLIT 教程第二期】Inline WRF-HYSPLIT 耦合

【HYSPLIT 教程第二期】Inline WRF-HYSPLIT 耦合

WW、forever的博客 808

指针进阶超详解

一、 字符指针 二、数组指针 三、指针数组 四、 数组传参和指针传参 五、函数指针 六、函数指针数组 七、指向函数指针数组的指针 八、回调函数 九、指针和数组面试题的解析

weixin_63246064的博客 1659

樽海鞘优化算法详解:原理、实现与应用

本文详细介绍了樽海鞘优化算法(SSA)的原理、实现与应用。该算法模拟樽海鞘链式群体行为,将优化问题解空间映射为群体移动空间,通过领导者引导和追随者跟随的协作机制寻找最优解。文章从生物特性、数学模型到Python代码实现进行了系统阐述,包括种群初始化、位置更新公式和收敛因子等核心要素,并展示了算法在函数优化等领域的应用潜力。该算法具有结构简单、参数少、实现容易等特点,在多种优化问题上表现良好。

qq_42212808的博客 644

详解之进阶指针

现在我们要一个数组,存放的是函数指针的地址,那我们直接再int ( * p)(int,int)上面动手脚,既然我们 要得到一个数组,那我们就在p后面加上[ ],即int ( * p[ ])(int,int),[ ]的优先级比 * 高,所以p先和[ ]结合成一个数组,这个时候去掉p[ ],剩下的就是p的类型,这里,把数组的地址赋值给p,p解引用操作就拿到了数组的地址,数组的地址是从首元素地址开始的,也就相当于拿到了数组的首元素地址,*p+i 就是拿到数组每个元素的地址最后进行解引用操作,就拿到了每个元素。

qq_74276498的博客 237

SIMATIC S7-1200, S7-1500 PID 控制[手册]

SIMATIC S7-1200, S7-1500 PID 控制[手册]

蓝牙模块HM-10手册

蓝牙模块HM-10手册,该手册对蓝牙模块HM-10进行了详细的介绍和使用方法以及一些AT指令。

让你不再惧怕指针——C语言指针及指针进阶详解

指针是C语言中一个重要的概念,理解它有助于更好地理解和利用C语言的强大功能。理解指针的概念和使用方法,可以提高程序的效率、灵活性和内存管理能力。理解和掌握它可以提高程序的效率和灵活性

qq_55119554的博客 777

华为的C语言编程规范.pdf

华为技术有限公司内部技术规范。本规范制定了编写C语言程序的基本原则、规则和建议。从代码的清晰、简洁、可测试、安全、程序效率、可移植各个方面对C语言编程作出了具体指导。

指针的进阶【详解】

整形指针即为指向整形数据地址的指针。字符指针即为指向字符数据地址的指针。数组指针即为指向数组地址的指针。函数指针即为指向函数地址的指针。* - 指向浮点数地址的指针。* - 指向整形地址的指针。* - 指向字符地址的指针。

小侯宝的博客 408

Devexpress16.2.6破解工具

Devexpress16.2.6破解工具Devexpress16.2.6破解工具Devexpress16.2.6破解工具Devexpress16.2.6破解工具

指针进阶详解(下)

指针在编程中非常重要。它们允许程序员直接访问和操作计算机内存中的数据。指针可以用于动态分配内存、传递参数、实现数据结构(如链表和树)以及优化程序性能。在指针进阶详解(上)中,我们已经介绍了部分指针进阶相关知识,接下来我们将继续介绍指针进阶相关知识。

Zhenyu_Coder的博客 612

【指针套娃】指针进阶详解

系列文章目录 文章目录系列文章目录前言字符指针指针数组数组指针数组指针的定义&数组名VS数组名数组指针的使用总结 前言 首先我们再来回顾一下指针的概念 指针就是个变量,用来存放地址,地址唯一标识一块内存空间。 指针的大小是固定的4/8个字节(32位平台/64位平台)。 指针是有类型,指针的类型决定了指针的+(-)整数的步长,指针解引用操作的时候的权限。 指针的运算。 字符指针 字符指针一般有两种: int main() { //第一种,指向单个字符 char ch='w';

qq_52145272的博客 918

C 语言进阶指针:字符指针、指针数组、数组指针、函数指针详解

本文从简要说明进阶指针(字符指针,指针数组,数组指针,函数指针)定义并给出例子,接着指出它们各自优缺点,最后结合相关代码示例,直观感受指针魅力。

2502_91275727的博客 923

[C语言]指针进阶详解

数组指针的本质是指针。整型指针:int* p;能够指向整形数据的指针浮点型指针:float* p;能够指向浮点型数据的指针所以说数组指针就是能够指向数组的指针。比如:(*p)代表p是指针,指向的是整型数组中的10个元素,每个元素是int类型。注意:[ ]的优先级要高于*号,因此必须加上()来保证p先和*相结合。3.2&数组名vs数组名对于下面的数组:arr和&arr的区别:我们知道arr是数组名,数组名表示数组首元素的地址。那么&arr表示的是什么?int main()

2401_83283514的博客 2069

C语言进阶——指针详解

本文介绍了指针的有关知识,适合初学者食用

都市隸人的博客 1078

C语言指针进阶详解

文章目录前言一、字符指针:二、指针数组:三、数组指针:四、函数指针:五、函数指针数组:六、指向函数指针数组的指针:总结 前言 我们在上一篇指针初阶博客中已经接触了指针,我们知道了指针的概念: 指针变量用来存放地址,地址相当于最小储存单元的编号。 指针的大小是固定的,在32/64位平台下为4/8字节。 指针有类型,类型决定了指针±整数移动的距离和解引用时的权限。 今天我们开始指针部分进阶的学习: 一、字符指针: 在指针初阶中我们知道有一种指针类型为字符指针char*,我们知道它指向一个字符,那我们再看

weixin_61661271的博客 2943

详解进阶指针

字符指针、指针数组、数组指针、函数指针以及指针的部分面试题

V5Jackeylove的博客 627

C语言指针和进阶指针详解。

C语言指针

zengbiao1的博客 1452

【C指针详解】进阶篇

C指针进阶:详解1. 字符指针2. 指针数组3. 数组指针3.1 数组指针的定义3.2 &数组名VS数组名3.3 数组指针的使用4. 数组参数、指针参数4.1 一维数组传参4.2 二维数组传参4.3 一级指针传参4.4 二级指针传参5. 函数指针5.1函数的地址5.2函数指针如何书写5.3函数指针如何使用5.4练习6. 函数指针数组 7.指针函数指针数组的指针

m0_70980326的博客 1314
上一篇: 指针和数组笔试题解析(最详细解析,没有之一)
下一篇: 冒泡排序模拟实现qsort()函数
小白debug~
小白debug~ 新星创作者: C/C++技术领域 新星创作者: C/C++技术领域
博客等级 码龄4年 3510粉丝 128原创
评论 57
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

小白debug~

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值